使用CAKeyframeAnimation的交错动画?

时间:2013-10-19 21:34:45

标签: ios core-animation

我希望在特定时间点为3个不同的图像制作动画,使其表现得如此。

1) 1st image moves from (Xx, Yx) to (Xz,Yz) 
2) Wait 10 seconds
3) 2nd image appears in place at Xa,Yb
4) Wait half as long as in step 2
5) Fade out 2nd image
6) 3rd image appears at the same place as 2nd image

如果这些图像的每个动画都在他们自己的CALayers上,我可以将CAKeyframeAnimation与多个图层一起使用吗?如果没有,那么采用交错动画的另一种方式是什么?

我正在尝试将扑克牌从屏幕外移动到特定位置,然后在几秒钟后在屏幕上显示其他一些技巧。

2 个答案:

答案 0 :(得分:3)

不,您无法使用关键帧动画为多个图层设置动画。给定的CAAnimation只能作用于单个图层。顺便说一下,这包括组图层。

如果你所做的只是在直线上移动图像,淡出和淡入,你为什么不使用UIView动画呢?看一下名字以animateWithDuration开头的方法:动画:那些可以让你同时创建多个动画,然后完成块可以触发其他动画。

如果由于某种原因需要使用图层动画,可以使用beginTime属性(CAAnimation对象具有这些属性,因为它们符合CAMediaTiming协议。)对于不属于动画组的CAAnimations,使用

animation.beginTime = CACurrentMediaTime() + delay;

延迟是一个双倍,以秒表示延迟。

如果延迟为0,则动画将开始。

第三个选项是将视图控制器设置为动画的委托,并使用animationDidStop:finished:方法链接动画。在我看来,这最终是最容易实施的方法。

答案 1 :(得分:2)

关于单个动画组不能为不同图层的属性设置动画的说法是不正确的。它可以。该技术是将动画组附加到上层,并在各个动画的关键路径中引用子层的属性。

这里是一个完整的示例,仅用于演示目的。启动后,该项目将显示两个“足迹”,这些足迹会交替出现在屏幕顶部。

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

}

说了这么多,我应该补充一点,如果要对诸如位置的核心属性进行动画处理,则使其成为视图并使用UIView关键帧动画来协调不同视图上的动画可能会更简单。仍然,关键是说用CAAnimationGroup无法完成 是错误的。