iOS 關鍵幀動畫
級別:★★☆☆☆
標籤:「iOS CAKeyframeAnimation」「iOS 關鍵幀動畫」「CAKeyframeAnimation values」「CAKeyframeAnimation path」
作者: Xs·H
審校: QiShare團隊
最近的專案需求涉及到一些動畫效果。對於基本的動畫,可以使用QiShare之前分享過的CABasicAnimation實現,而和路徑相關的動畫(例如圖1的折線動畫)可以使用CAKeyframeAnimation實現。
CAKeyframeAnimation和CABasicAnimation都是CAPropertyAnimation的子類。CABasicAnimation可以控制動畫的起點(fromValue
toValue
),而CAKeyframeAnimation可以控制動畫的全過程。所以,可以將CABasicAnimation理解成只關注起點和終點的CAKeyframeAnimation。
對比CABasicAnimation來說,CAKeyframeAnimation是通過控制動畫的關鍵幀和步調 (關鍵幀執行的時間)來控制動畫過程的。
1、CAKeyframeAnimation使用“values”或“path”屬性來控制動畫的關鍵幀
values:可選的NSArray物件,存放多個
value
,每個value
就是一個keyframe
(關鍵幀)。在動畫過程中,關鍵幀會依序顯示出來。 path:可選的CGPathRef物件,指定動畫的路徑,可讓CALayer的anchorPoint
和position
按照路徑變化。除了“moveTo”之外,路徑中的每個點都是一個關鍵幀。如果需要沿路徑勻速動畫,需要將calculationMode
屬性設定為paced
。當path
非nil
時,values
屬性被覆蓋。
2、CAKeyframeAnimation使用“keyTimes”屬性來控制動畫的步調
keyTimes: 可選的NSArray物件,存放多個
keyTime
,每個keyTime
都是[0, 1]區間內的浮點數所對應的NSNumber,與values
中的關鍵幀一一對應,控制關鍵幀發生的時間。 PS:當values
被path
覆蓋時,keyTimes
作用於path
。(path
的優先順序較高)
3、使用CAKeyframeAnimation實現圖1的折線動畫效果
為了輔助分析動畫過程,我們為動畫加上軌跡(後文只分析動畫本身,不分析軌跡),如圖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);
複製程式碼
4、使用CAKeyframeAnimation實現曲線動畫
CAKeyframeAnimation的values
和path
屬性具有強大的功能,尤其是path
,可以方便的制定自定義動畫路徑,比如圖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;
複製程式碼
示例原始碼可從GitHub的QiShare開源庫中獲取。
關注我們的途徑有:
QiShare(簡書)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公眾號)
推薦文章:
iOS 繪製漸變·基礎篇
iOS 繪製漸變·例項篇
iOS 編寫高質量Objective-C程式碼(七)
奇舞週刊