2017-03-01 55 views
0

我试图实现两个连续的转换动画。当第一个动画结束时,通过完成处理程序调用第二个动画。因为这是一个转换动画,所以我的问题是,当第一个动画完成时,图层将调整回原始大小,然后开始第二个动画。我希望第二个动画以第一个转换动画之后的新图层大小开始。这篇文章Objective-C - CABasicAnimation applying changes after animation?说我必须在开始第一个动画之前调整/转换图层,以便第一个动画结束时,图层实际上是新的大小。我试图通过改变边界或者实际上将变换应用到图层来实现,但它仍然不起作用。CALayer在转换动画后调回原始大小

override func viewDidAppear(_ animated: Bool) { 

    buildBar() 

} 

func buildBar(){ 

    progressBar1.bounds = CGRect(x: 0, y: 0, width: 20, height: 5) 
    progressBar1.position = CGPoint(x: 0, y: 600) 
    progressBar1.backgroundColor = UIColor.white.cgColor 
    view.layer.addSublayer(progressBar1) 
    extendBar1() 

} 


func extendBar1(){ 

    CATransaction.begin() 

    let transform1 = CATransform3DMakeScale(10, 1, 1) 
    let anim = CABasicAnimation(keyPath: "transform") 
    // self.progressBar1.bounds = CGRect(x: 0, y: 0, width: 200, height: 5) 
    // self.progressBar1.transform = transform1 
    anim.isRemovedOnCompletion = false 
    anim.fillMode = kCAFillModeForwards 
    anim.toValue = NSValue(caTransform3D:transform1) 
    anim.duration = 5.00 

    CATransaction.setCompletionBlock { 

     self.extendBar2() 
    } 

    progressBar1.add(anim, forKey: "transform") 
    CATransaction.commit() 
} 

func extendBar2(){ 

    let transform1 = CATransform3DMakeScale(2, 1, 1) 
    let anim = CABasicAnimation(keyPath: "transform") 
    anim.isRemovedOnCompletion = false 
    anim.fillMode = kCAFillModeForwards 
    anim.toValue = NSValue(caTransform3D:transform1) 
    anim.duration = 5.00 
    progressBar1.add(anim, forKey: "transform") 

} 

回答

0

因为要修改两个动画层的变换属性,它会更容易在这里使用CAKeyframeAnimation,它将处理动画为你的链接。

func extendBar(){ 
    let transform1 = CATransform3DMakeScale(10, 1, 1) 
    let transform2 = CATransform3DMakeScale(2, 1, 1) 

    let anim = CAKeyframeAnimation() 
    anim.keyPath = "transform" 
    anim.values = [progressBar1.transform, transform1, transform2] // the stages of the animation 
    anim.keyTimes = [0, 0.5, 1] // when they occurs, 0 being the very begining, 1 the end 
    anim.duration = 10.00 

    progressBar1.add(anim, forKey: "transform") 
    progressBar1.transform = transform2 // we set the transform property to the final animation's value 
} 

关于valueskeyTimes内容一个字:

  • 我们设定的第一个值是当前变换progressBar1。这将确保我们从当前图层的状态开始。
  • keyTimes中,我们说在开始时应使用values数组中的第一个值。然后我们在动画的一半时间说,该层应该被转换成values秒的值。因此,初始状态和第二个动画之间的动画将在此期间发生。然后,在0.5到1之间,我们将从tranform1transform2

您可以从objc.io网站了解更多关于动画this very nice article的信息。


如果你真的需要两个不同的动画(因为也许你想子视图添加到progressBar1之间,这里是一个将做到这一点

func extendBar1() { 
    CATransaction.begin() 
    CATransaction.setCompletionBlock { 
     print("side effects") 
     extendBar2() 
    } 
    let transform1 = CATransform3DMakeScale(5, 1, 1) 
    let anim = CABasicAnimation(keyPath: "transform") 

    anim.fromValue = progressBar1.transform 
    anim.toValue = transform1 
    anim.duration = 2.00 
    progressBar1.add(anim, forKey: "transform") 
    CATransaction.setDisableActions(true) 
    progressBar1.transform = transform1 
    CATransaction.commit() 
} 

func extendBar2() { 
    CATransaction.begin() 
    let transform2 = CATransform3DMakeScale(2, 1, 1) 
    let anim = CABasicAnimation(keyPath: "transform") 

    anim.fromValue = progressBar1.transform 
    anim.toValue = transform2 
    anim.duration = 2.00 
    progressBar1.add(anim, forKey: "transform") 
    CATransaction.setDisableActions(true) 
    progressBar1.transform = transform2 
    CATransaction.commit() 
} 

这里会发生什么码?基本上,我们设置一个第一个“正常动画”,所以我们创建动画,它将修改表示层并将实际图层设置为最终的第一个动画的变换

然后,当第一个动画完成后,我们将调用extendBar2,这将反过来排队一个正常的动画。

您还想在明确更新转换之前调用CATransaction.setDisableActions(true),否则,核心动画将创建一个隐式动画,它将覆盖之前创建的动画。

+0

是否有可能使用这个完成处理程序?我试图在两个动画之间做些什么,这就是为什么我有完成处理程序。 – Brosef

+0

哼,不,当达到关键帧动画的某些点时,你没有回调。让我花一分钟用两种不同的动画扩展我的答案,以便您可以使用完成处理程序。 – tomahh

+0

@Brosef一分钟变成12,但答案已更新:) – tomahh