/ / Dibujar línea animada - swift, animación, dibujar

Dibujar línea animada - rápida, animación, dibujar

Quiero tener una línea en el centro de la pantalla y animarla como una serpiente

Esta es una animación paso a paso que quiero hacer.

enter image description here

¿Cómo puedo hacer esto?

Respuestas

30 para la respuesta № 1

Puedes animar el final del trazo de un path en un CAShapeLayer, p.ej.,

weak var shapeLayer: CAShapeLayer?

@IBAction func didTapButton(_ sender: Any) {
// remove old shape layer if any

self.shapeLayer?.removeFromSuperlayer()

// create whatever path you want

let path = UIBezierPath()
path.move(to: CGPoint(x: 10, y: 50))
path.addLine(to: CGPoint(x: 200, y: 50))
path.addLine(to: CGPoint(x: 200, y: 240))

// create shape layer for that path

let shapeLayer = CAShapeLayer()
shapeLayer.fillColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0).cgColor
shapeLayer.strokeColor = #colorLiteral(red: 1, green: 0, blue: 0, alpha: 1).cgColor
shapeLayer.lineWidth = 4
shapeLayer.path = path.cgPath

// animate it

view.layer.addSublayer(shapeLayer)
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.fromValue = 0
animation.duration = 2
shapeLayer.add(animation, forKey: "MyAnimation")

// save shape layer

self.shapeLayer = shapeLayer
}

Eso rinde:

trayectoria trazada

Claramente, puedes cambiar el UIBezierPath a lo que convenga a vuestros intereses. Por ejemplo, podrías tener espacios en la ruta. O ni siquiera necesitas tener caminos rectilíneos:

let path = UIBezierPath()
path.move(to: CGPoint(x: 10, y: 130))
path.addCurve(to: CGPoint(x: 210, y: 200), controlPoint1: CGPoint(x: 50, y: -100), controlPoint2: CGPoint(x: 100, y: 350))

También puede combinar la animación tanto del inicio como del final del trazo en un CAAnimationGroup:

// create shape layer for that path (this defines what the path looks like when the animation is done)

let shapeLayer = CAShapeLayer()
shapeLayer.fillColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0).cgColor
shapeLayer.strokeColor = #colorLiteral(red: 1, green: 0, blue: 0, alpha: 1).cgColor
shapeLayer.lineWidth = 5
shapeLayer.path = path.cgPath
shapeLayer.strokeStart = 0.8

let startAnimation = CABasicAnimation(keyPath: "strokeStart")
startAnimation.fromValue = 0
startAnimation.toValue = 0.8

let endAnimation = CABasicAnimation(keyPath: "strokeEnd")
endAnimation.fromValue = 0.2
endAnimation.toValue = 1.0

let animation = CAAnimationGroup()
animation.animations = [startAnimation, endAnimation]
animation.duration = 2
shapeLayer.add(animation, forKey: "MyAnimation")

Flexible:

enter image description here

CoreAnimation le da mucho control sobre cómo se representa la ruta trazada.


2 para la respuesta № 2

Mi necesidad era algo similar: quería dejar que el movimiento de una forma trazara una línea en la escena, pero tenía grandes dificultades para sincronizar la animación en CAShapeLayer con la animación en SKScene.

Así que terminé usando un enfoque diferente:

import SpriteKit
import PlaygroundSupport
import AVFoundation

let start = CGPoint(x: 100, y: 50)
let end = CGPoint(x: 200, y: 50)
let control = CGPoint(x: 150, y: 100);
var motion: SKAction = SKAction();

let radius: CGFloat = 20;
let bounds = CGRect(x: 0, y: 0, width: 400, height: 200)
let skview = SKView(frame: bounds)
PlaygroundPage.current.liveView = skview
PlaygroundPage.current.needsIndefiniteExecution = true

class MyScene: SKScene,AVSpeechSynthesizerDelegate {
var motionComplete = false
var redline: SKShapeNode = SKShapeNode();
var greenball: SKShapeNode = SKShapeNode();
override func sceneDidLoad() {

greenball = SKShapeNode(circleOfRadius: radius);
greenball.position = start;
greenball.fillColor = .green;

let motionpath = CGMutablePath();

motionpath.move(to: start)
motionpath.addQuadCurve(to: end, control: control)

motion = SKAction.follow(motionpath, asOffset: false, orientToPath: true,duration: 2);

let linepath = CGMutablePath();
linepath.move(to: start);
redline = SKShapeNode(path: linepath);
redline.strokeColor = .red;
redline.lineWidth = 5;

greenball.run(motion) {
self.motionComplete = true;
};

self.addChild(greenball);
self.addChild(redline);
}

override func update(_ currentTime: TimeInterval) {

if (motionComplete == false) {
let cgpath = self.redline.path as! CGMutablePath;
cgpath.addLine(to: greenball.position);
self.redline.path = cgpath;

}
}


}



let scene = MyScene(size: CGSize(width: 400, height: 200));
scene.scaleMode = SKSceneScaleMode.aspectFill
scene.size = skview.bounds.size
skview.presentScene(scene)

Resultado:

enter image description here


0 para la respuesta № 3

Un método es usar una vista UIV con el color de fondo. Intenta algo como esto.

let screenWidth = UIScreen.main.bounds.width
let screenHeight = UIScreen.main.bounds.height
let redLine = UIView()
redline.backgroundColor = UIColor.red
redLine.frame = GCRect(x: screenWidth / 2, y: screenHeight / 2, width: 0, height: 0)

UIView.animate(withDuration: 2, animations: {
redLine.frame = GCRect(x: screenWidth / 2, y: screenHeight / 2, width: 0, height: (screenHeight / 2) - 4)
}) { finished in
redLine.frame = GCRect(x: screenWidth / 2, y: (screenHeight / 2) - 4, width: 0, height: 1)
}

Con esto, puedes lograr cualquier cantidad de movimiento de línea roja.

El otro método es dibujar una línea. No voy a entrar en detalles sobre eso, pero recomendaría Este artículo.

Una última cosa... En el desbordamiento de pila apreciamos a las personas que demuestran que investigaron correctamente un tema antes de hacer una pregunta. Usando Google, pude encontrar rápidamente muchos tutoriales sobre cómo hacer lo que estás buscando. Intente realizar una investigación usted mismo, porque a menudo un tutorial tendrá muchos más detalles que es importante que una respuesta de desbordamiento de pila.