通常要實現沿著復雜路徑的動畫,我們可以借助關鍵幀動畫(CAKeyframeAnimation)來實現。由於 CAKeyframeAnimation 提供了的便利的 path 屬性,我們只需要對其設置相應的路徑即可。
1,准備工作
首先我們在頁面上添加一個橙色的方塊,後面通過對這個方塊添加軌跡動畫來演示CAKeyframeAnimation的使用。
import UIKit
class ViewController: UIViewController {
var square:UIView!
override func viewDidLoad() {
super.viewDidLoad()
square = UIView(frame:CGRectMake(0, 0, 20, 20))
square.backgroundColor = UIColor.orangeColor()
self.view.addSubview(square)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
2,做圓周運動
下面樣例中方塊會沿著圓形的軌跡做圓周運動(只播放一次)
(1)通過 CGPathCreateWithEllipseInRect() 方法,我們創建一個圓形的 CGPath 作為我們的關鍵幀動畫的 path。
(2)將 calculationMode 設置為 kCAAnimationPaced,讓 Core Animation 向被驅動的對象施加一個恆定速度,不管路徑的各個線段有多長。
let centerX = view.bounds.size.width/2
let boundingRect:CGRect = CGRectMake(centerX-75, 50, 150, 150)
let orbit = CAKeyframeAnimation(keyPath:"position")
orbit.duration = 3
orbit.path = CGPathCreateWithEllipseInRect(boundingRect,nil)
orbit.calculationMode = kCAAnimationPaced
square.layer.addAnimation(orbit,forKey:"Move")
3,讓圖層保持顯示動畫執行後的狀態
默認情況下動畫執行完畢後,圖形會恢復到動畫執行前的狀態。比如上面樣例,方塊移動一周後又會跑到頁面坐上角位置。如果想讓方塊保持顯示動畫執行後的狀態,有如下兩種方式:
(1)動畫下方代碼直接設置方塊最終位置坐標
let centerX = view.bounds.size.width/2
let boundingRect:CGRect = CGRectMake(centerX-75, 50, 150, 150)
let orbit = CAKeyframeAnimation(keyPath:"position")
orbit.duration = 3
orbit.path = CGPathCreateWithEllipseInRect(boundingRect,nil)
orbit.calculationMode = kCAAnimationPaced
square.layer.addAnimation(orbit,forKey:"Move")
//下面代碼讓方塊運動一周後停留在終點位置(否則會回到原來的位置)
square.layer.position = CGPointMake(centerX+75, 125)
(2)將動畫的 removedOnCompletion 屬性那就設置為false,fillMode 設置為 kCAFillModeForwards。
let centerX = view.bounds.size.width/2
let boundingRect:CGRect = CGRectMake(centerX-75, 50, 150, 150)
let orbit = CAKeyframeAnimation(keyPath:"position")
orbit.duration = 3
orbit.path = CGPathCreateWithEllipseInRect(boundingRect,nil)
orbit.calculationMode = kCAAnimationPaced
orbit.removedOnCompletion = false
orbit.fillMode = kCAFillModeForwards
square.layer.addAnimation(orbit,forKey:"Move")
4,在軌跡上重復運動
repeatCount 參數可以設置動畫的重復次數,將其設為 HUGE 可以讓方塊圓周運動動畫一直循環播放下去。
let centerX = view.bounds.size.width/2
let boundingRect:CGRect = CGRectMake(centerX-75, 50, 150, 150)
let orbit = CAKeyframeAnimation(keyPath:"position")
orbit.duration = 3
orbit.path = CGPathCreateWithEllipseInRect(boundingRect,nil)
orbit.calculationMode = kCAAnimationPaced
orbit.repeatCount = HUGE
square.layer.addAnimation(orbit,forKey:"Move")
5,讓方塊沿著路徑旋轉
設置 rotationMode 屬性為 kCAAnimationRotateAuto 可以讓方塊沿著路徑旋轉,即方塊不管移動到哪個位置,它始終朝向圓心。
let centerX = view.bounds.size.width/2
let boundingRect:CGRect = CGRectMake(centerX-75, 50, 150, 150)
let orbit = CAKeyframeAnimation(keyPath:"position")
orbit.duration = 3
orbit.path = CGPathCreateWithEllipseInRect(boundingRect,nil)
orbit.calculationMode = kCAAnimationPaced
orbit.repeatCount = HUGE
orbit.rotationMode = kCAAnimationRotateAuto
square.layer.addAnimation(orbit,forKey:"Move")
6,構建更加復雜的路徑
通過 CGPathCreateMutable,我們可以將多條弧線、直線等拼接成一個復雜的路徑,讓方塊在這個路徑上運動。
let centerX = view.bounds.size.width/2
//創建用於轉移坐標的Transform,這樣我們不用按照實際顯示做坐標計算
var transform:CGAffineTransform = CGAffineTransformMakeTranslation(centerX, 50);
let path = CGPathCreateMutable()
CGPathMoveToPoint(path, &transform, 0, 0);
CGPathAddLineToPoint(path, &transform, 0, 75);
CGPathAddLineToPoint(path, &transform, 75, 75);
CGPathAddArc(path, &transform, 0, 75, 75, 0, CGFloat(1.5 * M_PI), false);
let orbit = CAKeyframeAnimation(keyPath:"position")
orbit.duration = 3
orbit.path = path
orbit.calculationMode = kCAAnimationPaced
orbit.repeatCount = HUGE
//orbit.rotationMode = kCAAnimationRotateAuto
square.layer.addAnimation(orbit,forKey:"Move")
7,使用動畫組實現多種動畫的組合
通過動畫組(CAAnimationGroup),我們可以將多個動畫組合在一起同時播放。
下面的樣例中,小方塊沿著軌跡運動的同時,自身還會快速地旋轉。(方塊移動一周,自身會旋轉100次)
//旋轉動畫
let rotateAnimation = CAKeyframeAnimation(keyPath:"transform.rotation.z")
rotateAnimation.values = [0,200*M_PI]
//軌跡動畫路徑
let centerX = view.bounds.size.width/2
//創建用於轉移坐標的Transform,這樣我們不用按照實際顯示做坐標計算
var transform:CGAffineTransform = CGAffineTransformMakeTranslation(centerX, 50);
let path = CGPathCreateMutable()
CGPathMoveToPoint(path, &transform, 0, 0);
CGPathAddLineToPoint(path, &transform, 0, 75);
CGPathAddLineToPoint(path, &transform, 75, 75);
CGPathAddArc(path, &transform, 0, 75, 75, 0, CGFloat(1.5 * M_PI), false);
//軌跡動畫
let orbitAnimation = CAKeyframeAnimation(keyPath:"position")
orbitAnimation.path = path
orbitAnimation.calculationMode = kCAAnimationPaced
//組合兩個動畫
let animationgroup = CAAnimationGroup()
animationgroup.animations = [rotateAnimation, orbitAnimation]
animationgroup.duration = 4
animationgroup.repeatCount = HUGE
square.layer.addAnimation(animationgroup,forKey:"Move")
原文出自:http://www.hangge.com/blog/cache/detail_1072.html