CALayer在变换动画后调整回原始大小

时间:2017-03-01 01:47:20

标签: ios swift3 calayer cabasicanimation

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

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

}

1 个答案:

答案 0 :(得分:0)

因为您要在两个动画中修改图层的transform属性,所以在这里使用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数组中的第一个值。然后我们在动画的中场时间说,该层应该以{{1​​}}秒的值转换。因此,初始状态和第二个状态之间的动画将在该时间期间发生。然后,在0.5到1之间,我们将从values转到tranform1

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

如果你真的需要两个不同的动画(因为你可能想要在两者之间添加子视图{/ 1}},这里的代码就是

transform2

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

然后,当第一个动画完成时,我们调用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() } ,否则,核心动画将创建一个隐式动画,它将覆盖之前创建的动画。