如何在完成后重新启动 CABasicAnimation

How to restart a CABasicAnimation after it is completed

我有一个按钮,当按下它时 运行在 2 秒内生成一个 CABasicAnimation。我第一次按下按钮时,动画 运行 很好,图层被填充为红色。我第二次按下按钮时,动画不再 运行。红色层消失了,因为我删除了它,但它不会再次从头开始。

在下面的代码中,basicAnimation 是一个class属性。我还尝试在 buttonPressed 方法本身内部创建它,这没有任何区别,然后我尝试将其添加为可选 var basicAnimation: CABasicAnimation?,在 buttonPressed 方法中实例化它,然后在 animationDidStop(_:finished:) 委托方法中将其设置为 nil但都没有用。

为什么不再是 运行?

let shapeLayer = CAShapeLayer()

let basicAnimation = CABasicAnimation(keyPath: "strokeEnd")
// var basicAnimation: CABasicAnimation? // I tried this

override func viewDidLoad() {
    super.viewDidLoad()

    let circularPath = UIBezierPath(arcCenter: view.center, radius: 100, startAngle: -.pi/2, endAngle: 3 * .pi/2, clockwise: true)
    shapeLayer.path = circularPath.cgPath
    shapeLayer.strokeColor = UIColor.red.cgColor
    shapeLayer.fillColor = UIColor.clear.cgColor
    shapeLayer.lineWidth = 10
    shapeLayer.strokeEnd = 0
    view.layer.addSublayer(shapeLayer)
}

@objc func buttonTapped() {

    // basicAnimation = CABasicAnimation(keyPath: "strokeEnd") // I tried this
    // let basicAnimation = CABasicAnimation(keyPath: "strokeEnd") // I also tried this
    removeAnimation()

    basicAnimation.delegate = self
    basicAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.default)
    basicAnimation.fromValue = 0
    basicAnimation.toValue = 1
    basicAnimation.duration = CFTimeInterval(2)
        
    basicAnimation.fillMode = CAMediaTimingFillMode.forwards
    basicAnimation.isRemovedOnCompletion = false
        
    shapeLayer.add(basicAnimation, forKey: "myAnimation")
}

func removeAnimation() {
    shapeLayer.removeAnimation(forKey: "myAnimation")
}

func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
    print("animation done") // prints once

    // basicAnimation = nil // I tried this
}

每次点击按钮时制作一个新动画,我就能让你的代码正常工作:

let shapeLayer = CAShapeLayer()

var basicAnimation: CABasicAnimation!

override func viewDidLoad() {
    super.viewDidLoad()

    let circularPath = UIBezierPath(arcCenter: view.center, radius: 100, startAngle: -.pi/2, endAngle: 3 * .pi/2, clockwise: true)
    shapeLayer.path = circularPath.cgPath
    shapeLayer.strokeColor = UIColor.red.cgColor
    shapeLayer.fillColor = UIColor.clear.cgColor
    shapeLayer.lineWidth = 10
    shapeLayer.strokeEnd = 0
    view.layer.addSublayer(shapeLayer)
}

@IBAction func buttonTapped(_ sender: Any) {

    basicAnimation = CABasicAnimation(keyPath: "strokeEnd")
    removeAnimation()

    basicAnimation.delegate = self
    basicAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.default)
    basicAnimation.fromValue = 0
    basicAnimation.toValue = 1
    basicAnimation.duration = CFTimeInterval(2)
        
    basicAnimation.fillMode = CAMediaTimingFillMode.forwards
    basicAnimation.isRemovedOnCompletion = false
        
    shapeLayer.add(basicAnimation, forKey: "myAnimation")
}

func removeAnimation() {
    shapeLayer.removeAnimation(forKey: "myAnimation")
}

func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
    print("animation done")
}