Staggered animations with CAKeyframeAnimation?

前端 未结 2 1505
轮回少年
轮回少年 2021-01-16 03:55

I want to animate 3 different images at specific point in time such that it behaves this way.

1) 1st image moves from (Xx, Yx) to (Xz,Yz) 
2) Wait 10 seconds         


        
2条回答
  •  不思量自难忘°
    2021-01-16 04:31

    The claim that a single animation group cannot animate properties of different layers is not true. It can. The technique is to attach the animation group to the superlayer and refer to the properties of the sublayers in the individual animations' key paths.

    Here is a complete example just for demonstration purposes. When launched, this project displays two "footprints" that proceed to step in alternation, walking off the top of the screen.

    class ViewController: UIViewController, CAAnimationDelegate {
    
        let leftfoot = CALayer()
        let rightfoot = CALayer()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            
            self.leftfoot.name = "left"
            self.leftfoot.contents = UIImage(named:"leftfoot")!.cgImage
            self.leftfoot.frame = CGRect(x: 100, y: 300, width: 50, height: 80)
            self.view.layer.addSublayer(self.leftfoot)
    
            self.rightfoot.name = "right"
            self.rightfoot.contents = UIImage(named:"rightfoot")!.cgImage
            self.rightfoot.frame = CGRect(x: 170, y: 300, width: 50, height: 80)
            self.view.layer.addSublayer(self.rightfoot)
    
            DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
                self.start()
            }
        }
    
        func start() {
            let firstLeftStep = CABasicAnimation(keyPath: "sublayers.left.position.y")
            firstLeftStep.byValue = -80
            firstLeftStep.duration = 1
            firstLeftStep.fillMode = .forwards
    
            func rightStepAfter(_ t: Double) -> CABasicAnimation {
                let rightStep = CABasicAnimation(keyPath: "sublayers.right.position.y")
                rightStep.byValue = -160
                rightStep.beginTime = t
                rightStep.duration = 2
                rightStep.fillMode = .forwards
                return rightStep
            }
            func leftStepAfter(_ t: Double) -> CABasicAnimation {
                let leftStep = CABasicAnimation(keyPath: "sublayers.left.position.y")
                leftStep.byValue = -160
                leftStep.beginTime = t
                leftStep.duration = 2
                leftStep.fillMode = .forwards
                return leftStep
            }
    
            let group = CAAnimationGroup()
            group.duration = 11
            group.animations = [firstLeftStep]
            for i in stride(from: 1, through: 9, by: 4) {
                group.animations?.append(rightStepAfter(Double(i)))
                group.animations?.append(leftStepAfter(Double(i+2)))
            }
            group.delegate = self
            self.view.layer.add(group, forKey: nil)
        }
        
        func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
            print("done")
            self.rightfoot.removeFromSuperlayer()
            self.leftfoot.removeFromSuperlayer()
        }
    
    }
    

    Having said all that, I should add that if you are animating a core property like the position of something, it might be simpler to make it a view and use a UIView keyframe animation to coordinate animations on different views. Still, the point is that to say that this cannot be done with CAAnimationGroup is just wrong.

提交回复
热议问题