2017-03-01 58 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