? ? ? 核心動畫,即Core Animation,是Apple封裝的一組非常好用且強大的動畫API。它直接作用于Layer層,通過 - (void)addAnimation:(CAAnimation*)anim forKey:(nullableNSString*)key ,即可讓動畫生效。
? ? ? ?創建核心動畫,使用的是CAAnimation的子類,分別是基礎動畫(CABasicAnimation),關鍵幀動畫(CAKeyframeAnimation),轉場動畫(CATransition)和組動畫(CAAnimationGroup)。我做了個他們之間的關系草圖如下。
? ? ? CAAnimationDelegate是核心動畫的代理,通過其可以在動畫開始與結束階段進行一些操作,不過需要注意的是在iOS9以前CAAnimationDelegate是CAAnimation的類別,之后才是代理,且為強引用。因此使用CAAnimationDelegate需判斷當前系統版本,并且在當前頁面dealloc之前需先動畫移除,否則會出現無法釋放的內存問題。
? 下圖為我寫過的一個小動畫,分析一下其中使用的動畫來簡單介紹一下核心動畫。
1、CABasicAnimation基礎動畫
? ? ? ? GIF圖中,血量彈性變化,猴子轉身以及受傷抖動動畫都都使用了基礎動畫。受傷抖動動畫的代碼如下,
CABasicAnimation*Animation = [CABasicAnimationanimationWithKeyPath:@"position"];
Animation.fromValue= [NSValuevalueWithCGPoint:CGPointMake(pet.centerX, pet.centerY)];
Animation.toValue= [NSValuevalueWithCGPoint:CGPointMake(pet.centerX+5, pet.centerY)];
Animation.autoreverses=YES;
//Animation.beginTime=CACurrentMediaTime()+0.8;
//Animation.removedOnCompletion=NO;
Animation.fillMode=kCAFillModeBackwards;
Animation.repeatCount=10;
Animation.duration=0.02;//一次時間
屬性解析
? ? ? CABasicAnimationanimationWithKeyPath? ? 動畫路徑,告訴系統需要執行的動畫類型 。position為位置,而猴子旋轉路徑則為transform.rotation.z。
? ? ? ?fromValue,toValue ? ?動畫的起始值與終止值
? ? ? ?autoreverses ? ?動畫是否沿原路徑返回
? ? ? fillMode? 分kCAFillModeForwards,kCAFillModeBackwards,kCAFillModeBoth,kCAFillModeRemoved四中模式。當你設置removedOnCompletion值為NO時,kCAFillModeForwards可以讓當前視圖保持在動畫最后的位置;當你設置了延遲執行時(beginTime),kCAFillModeBackwards會在代碼執行時,使layer層進入動畫開始階段的位置,而結束后會返回layer本身位置;kCAFillModeBoth就很好理解了,如果removedOnCompletion = NO那layer會在動畫開始之前就會迅速進入動畫的初始位置并在執行完動畫后停在動畫結束的位置,如果removedOnCompletion = YES那layer會在動畫開始之前就會迅速進入動畫的初始位置并在執行完動畫后迅速返回到layer的本身位置。
? ? ? ?repeatCount ? 重復次數
? ? ? ? duration 動畫時間
血量彈性變化,使用的是基礎動畫的子類CASpringAnimation。它有幾個屬性,分別是
mass,對象質量質量越大彈性越大需要的動畫時間越長。
stiffness,剛度系數,剛度系數越大,產生形變的力就越大,運動越快。
damping,阻尼系數阻止彈簧伸縮的系數阻尼系數越大,停止越快。時間越短。
initialVelocity,初始速度,正負代表方向,數值代表大小。
2,關鍵幀動畫與組動畫
GIF圖中,香蕉茄子的飛行動畫使用的為組動畫,組動畫中包含了兩個關鍵幀動畫和一個旋轉組動畫。CAAnimationGroup的animations屬性可以將動畫放到數組中,同時執行。
其中物品的飛行過程中的大小變化代碼
CGFloatfrom3DScale =1+arc4random() %10*0.1;
CGFloatto3DScale =1;
CAKeyframeAnimation*Animation = [CAKeyframeAnimationanimationWithKeyPath:@"transform"];
Animation.values=@[[NSValuevalueWithCATransform3D:CATransform3DMakeScale(from3DScale, from3DScale, from3DScale)], [NSValuevalueWithCATransform3D:CATransform3DMakeScale(to3DScale, to3DScale, to3DScale)]];
Animation.timingFunctions=@[[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseOut], [CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseIn]];
? ? ? ? ? 關鍵幀動畫相對于基礎動畫的區別是,CABasicAnimation只能從一個數值(fromValue)變到另一個數值(toValue),而CAKeyframeAnimation會使用一個NSArray保存這些數值。timingFunctions則是動畫的節奏。
飛行動畫代碼
CGMutablePathRefpathOne =CGPathCreateMutable();
CGPathMoveToPoint(pathOne,NULL, start.x, start.y);
CGPathAddQuadCurveToPoint(pathOne,NULL, start.x, -1, end.x, end.y);
CAKeyframeAnimation*animationOne = [CAKeyframeAnimationanimationWithKeyPath:@"position"];
[animationOnesetPath:pathOne];
animationOne.duration=1.2;
animationOne.fillMode=kCAFillModeForwards;
animationOne.removedOnCompletion=NO;
CFRelease(pathOne);
pathOne =nil;
? ? ? ? 飛行路徑的path可以通過CGPathRef\CGMutablePathRef繪制,讓層跟著路徑移動。path只對CALayer的anchorPoint和position起作用。如果你設置了path,那么values將被忽略。需要注意的是,需要手動繪制的路徑釋放。若想細致控制動畫,還可設置keyTimes,為對應的關鍵幀指定對應的時間點,其取值范圍為0到1.0,keyTimes中的每一個時間值都對應values中的每一幀。當keyTimes沒有設置的時候,各個關鍵幀的時間是平分的。
3,轉場動畫
? ? ? ? ?此GIF中沒有用到,它能夠為層提供移出屏幕和移入屏幕的動畫效果。其實UINavigationController就是通過CATransition實現了將控制器的視圖推入屏幕的動畫效果。說明一下它的幾個屬性。
type:動畫過渡類型
subtype:動畫過渡方向
startProgress:動畫起點(在整體動畫的百分比)
endProgress:動畫終點(在整體動畫的百分比)