Chcę mieć linię pośrodku ekranu i animować ją jak wąż
To jest animacja krok po kroku, którą chcę wykonać
Jak mogę to zrobić?
Odpowiedzi:
30 dla odpowiedzi nr 1Możesz animować koniec suwu path
na CAShapeLayer
np.
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
}
To daje:
Oczywiście, możesz zmienić UIBezierPath
do tego, co pasuje do twoich zainteresowań. Na przykład możesz mieć spacje na ścieżce. Lub nawet nie musisz mieć ścieżek prostoliniowych:
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))
Możesz także połączyć animację zarówno początku, jak i końca obrysu w a 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")
Wydajność:
CoreAnimation daje ci dużą kontrolę nad sposobem renderowania obcinanej ścieżki.
2 dla odpowiedzi nr 2
Moja potrzeba była podobna - chciałem, aby ruch kształtu śledził linię w scenie, ale miał wielką trudność w synchronizowaniu animacji w CAShapeLayer z animacją w SKScene.
Tak zakończyło się przy użyciu innego podejścia:
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)
Wynik:
0 dla odpowiedzi № 3
Jedną z metod jest użycie UIView z kolorem tła. Spróbuj czegoś takiego.
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)
}
Dzięki temu możesz osiągnąć dowolną ilość ruchu czerwonej linii.
Inną metodą jest narysowanie linii. Nie powiem o tym szczegółowo, ale polecam Ten artykuł.
Ostatnia rzecz... W przepełnieniu stosu doceniamy ludzi, którzy pokazują, że właściwie badali dany temat, zanim zadają pytanie. Używając google, mogłem szybko wymyślić wiele samouczków, jak robić to, czego szukasz. Postaraj się przeprowadzić badania samemu, ponieważ często samouczek będzie miał o wiele więcej szczegółów, niż jest to konieczne.