【问题标题】:How to restart a CABasicAnimation after it is completed完成后如何重新启动 CABasicAnimation
【发布时间】:2020-07-03 02:43:47
【问题描述】:

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

在下面的代码中,basicAnimation 是一个类属性。我还尝试在 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
}

【问题讨论】:

    标签: ios swift cabasicanimation


    【解决方案1】:

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

    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")
    }
    

    【讨论】:

    • 不过,您的代码还有其他问题。但是你没有问他们,所以我没有费心去讨论他们。 :)
    • 我 c+p 您的代码(这与我的代码完全一样),但它并没有做您正在做的事情。我一定在其他地方有问题,嗯。我什至添加了 print(Unmanaged.passUnretained(basicAnimation!).toOpaque()) 并且每次都会打印不同的内存地址。很奇怪
    • 好吧,如果有问题,它不在您显示的代码范围内。如果我发布整个测试项目,你会被说服吗?
    • 你是对的,是手势识别器导致了问题。一旦我删除它,动画效果很好。非常感谢并感谢您让我知道动画不能重复使用。非常有帮助:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-28
    • 2021-10-15
    相关资源
    最近更新 更多