iOS 關鍵幀動畫
級別:★★☆☆☆
標籤:「iOS CAKeyframeAnimation」「iOS 關鍵幀動畫」「CAKeyframeAnimation values」「CAKeyframeAnimation path」
作者:Xs·H
審校:QiShare團隊
最近的專案需求涉及到一些動畫效果。對於基本的動畫,可以使用QiShare之前分享過的CABasicAnimation實現,而和路徑相關的動畫(例如圖1的折線動畫)可以使用CAKeyframeAnimation實現。

圖1 折線動畫效果
CAKeyframeAnimation和CABasicAnimation都是CAPropertyAnimation的子類。CABasicAnimation可以控制動畫的起點( fromValue
)和終點( toValue
),而CAKeyframeAnimation可以控制動畫的全過程。所以,可以將CABasicAnimation理解成只關注起點和終點的CAKeyframeAnimation。
對比CABasicAnimation來說,CAKeyframeAnimation是通過控制動畫的 “關鍵幀” 和 “步調” (關鍵幀執行的時間)來控制動畫過程的。
一、CAKeyframeAnimation使用“values”或“path”屬性來控制動畫的關鍵幀
values:可選的NSArray物件,存放多個 value
,每個 value
就是一個 keyframe
(關鍵幀)。在動畫過程中,關鍵幀會依序顯示出來。
path:可選的CGPathRef物件,指定動畫的路徑,可讓CALayer的 anchorPoint
和 position
按照路徑變化。除了“moveTo”之外,路徑中的每個點都是一個關鍵幀。如果需要沿路徑勻速動畫,需要將 calculationMode
屬性設定為 paced
。當 path
非 nil
時, values
屬性被覆蓋。
二、CAKeyframeAnimation使用“keyTimes”屬性來控制動畫的步調
keyTimes: 可選的NSArray物件,存放多個 keyTime
,每個 keyTime
都是[0, 1]區間內的浮點數所對應的NSNumber,與 values
中的關鍵幀一一對應,控制關鍵幀發生的時間。
PS:當 values
被 path
覆蓋時, keyTimes
作用於 path
。( path
的優先順序較高)
三、使用CAKeyframeAnimation實現圖1的折線動畫效果
為了輔助分析動畫過程,我們為動畫加上軌跡(後文只分析動畫本身,不分析軌跡),如圖2。

圖2 帶軌跡的折線動畫效果
1) 像使用CABasicAnimation一樣初始化CAKeyframeAnimation的物件
// 初始化動畫 self.animation = [CAKeyframeAnimation animation]; self.animation.keyPath = @"position"; self.animation.delegate = self; self.animation.duration = 5.0; self.animation.repeatCount = 1.0; self.animation.removedOnCompletion = NO; self.animation.fillMode = kCAFillModeForwards; self.animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
2) 使用“values”和“keyTimes”屬性設定動畫的關鍵幀和步調
// 設定動畫的關鍵幀陣列 self.animation.values = @[[NSValue valueWithCGPoint:self.imageView.center],// 不能省略起點(1, 1) [NSValue valueWithCGPoint:(CGPoint){self.squareSide * 2, self.squareSide * 1}],// 右移1格 [NSValue valueWithCGPoint:(CGPoint){self.squareSide * 2, self.squareSide * 5}],// 下移4格 [NSValue valueWithCGPoint:(CGPoint){self.squareSide * 5, self.squareSide * 5}],// 右移3格 [NSValue valueWithCGPoint:(CGPoint){self.squareSide * 5, self.squareSide * 7}]// 下移2格 ]; // 設定動畫的步調 self.animation.keyTimes = @[@.0, @.1, @.5, @.8, @1.0]; // self.animation.calculationMode = kCAAnimationPaced;// 可以替代上面的keyTimes實現勻速效果
PS: 上述程式碼中的 keyTimes
是根據 values
的值進行設定的,以達到動畫勻速的效果。若不設定 keyTimes
,動畫時長( duration
)將被平均分配給4段動畫。
3) 像使用CABasicAnimation一樣為layer新增動畫和移除動畫
if (start) { [self.imageView.layer addAnimation:_animation forKey:@"animation"];// 執行動畫 } else { [self.imageView.layer removeAnimationForKey:@"animation"];// 移除動畫 }
上面有介紹到, path
屬性同樣可以設定動畫的關鍵幀,並且當 path
不為 nil
時會覆蓋 values
。
所以, 步驟2) 可以替換為 “path”
和 “keyTimes”
的方式。
CGMutablePathRef path = CGPathCreateMutable(); CGPathMoveToPoint(path, NULL, self.imageView.center.x, self.imageView.center.y); CGPathAddLineToPoint(path, NULL, self.squareSide * 2, self.squareSide * 1);// 右移1格 CGPathAddLineToPoint(path, NULL, self.squareSide * 2, self.squareSide * 5);// 下移4格 CGPathAddLineToPoint(path, NULL, self.squareSide * 5, self.squareSide * 5);// 右移3格 CGPathAddLineToPoint(path, NULL, self.squareSide * 5, self.squareSide * 7);// 下移2格 self.animation.keyTimes = @[@.0, @.1, @.5, @.8, @1.0]; // self.animation.calculationMode = kCAAnimationPaced;// 可以替代上面的keyTimes實現勻速效果 self.animation.path = path; CGPathRelease(path);
四、使用CAKeyframeAnimation實現曲線動畫
CAKeyframeAnimation的 values
和 path
屬性具有強大的功能,尤其是 path
,可以方便的制定自定義動畫路徑,比如圖3的橢圓動畫效果。

圖3 橢圓動畫效果
使用path制定上述橢圓路徑的程式碼如下:
CGRect drawRect = (CGRect){self.squareSide, self.squareSide, self.squareSide * 8, self.squareSide * 6}; CGMutablePathRef path = CGPathCreateMutable(); CGPathAddEllipseInRect(path, NULL, drawRect); self.animation.keyTimes = @[@.0, @.25, @0.5, @0.75, @1.0]; // self.animation.calculationMode = kCAAnimationPaced; self.animation.path = path;
ofollow,noindex">示例原始碼 可從GitHub的 QiShare開源庫 中獲取。
關注我們的途徑有:
QiShare(微信公眾號)