關(guān)于 Core Animation
Core Animation是一組非常強大的動畫處理API,使用它能做出很多優(yōu)雅的動畫效果。能用的動畫類有4個子類:CABasicAnimation、CAKeyframeAnimation、CATransition、CAAnimationGroup
開發(fā)步驟:
- 初始化一個動畫對象(CAAnimation)并設(shè)置一些動畫相關(guān)屬性.
- 添加動畫對象到層(CALayer)中,開始執(zhí)行動畫.
CALayer中很多屬性都可以通過CAAnimation實現(xiàn)動畫效果, 包括opacity, position, transform, bounds, contents等,具體可以在API文檔中查找
通過調(diào)用CALayer的addAnimation:forKey:增加動畫到層(CALayer)中,這樣就能觸發(fā)動畫了.通過調(diào)用removeAnimationForKey:可以停止層中的動畫.
注:Core Animation的動畫執(zhí)行過程都是在后臺操作的,不會阻塞主線程.
創(chuàng)建動畫時你可能用到的屬性
屬性 | 解讀
----|------|----
Autoreverses | 設(shè)定這個屬性為 YES 時,在它到達目的地之后,動畫的返回到開始的值,代替了直接跳轉(zhuǎn)到開始的值,過渡平滑
Duration |設(shè)定開始值到結(jié)束值花費的時間。期間會被速度的屬性所影響
RemovedOnCompletion | 這個屬性默認為 YES,在指定的時間段完成后,動畫就自動的從層上移除了。
FillMode | 這個屬性一般和 RemovedOnCompletion 配合使用,保持動畫狀態(tài)。其中kCAFillModeForwards 當動畫結(jié)束后,layer會一直保持著動畫最后的狀態(tài).此時將RemovedOnCompletion設(shè)為NO
Speed | 默認的值為 1.0.如果你改變這個值為 2.0,動畫會用 2 倍的速度播放。這樣的影響就是使持續(xù)時間減半。如果你指定的持續(xù)時間為 6 秒,速度為 2.0,動畫就會播放 3 秒鐘即一半的持續(xù)時間。
RepeatCount | 默認的是 0,動畫只會播放一次。如果指定一個無限大的重復(fù)次數(shù),使用 MAXFLOAT 。這個不應(yīng)該和 repeatDration 屬性一塊使用
RepeatDuration | 這個屬性指定了動畫應(yīng)該被重復(fù)多久。動畫會一直重復(fù),直到設(shè)定的時間用完。同上它不應(yīng)該和 repeatCount 一起使用
FromValue | 設(shè)置動畫的初始值
ToValue | 設(shè)置動畫的到達值
TimingFunction | 控制動畫運行的節(jié)奏. kCAMediaTimingFunctionLinear(線性):勻速,給你一個相對靜態(tài)的感覺 kCAMediaTimingFunctionEaseIn(漸進):動畫緩慢進入,然后加速離開 kCAMediaTimingFunctionEaseOut(漸出):動畫全速進入,然后減速的到達目的地 kCAMediaTimingFunctionEaseInEaseOut(漸進漸出):動畫緩慢的進入,中間加速,然后減速的到達目的地。這個是默認的動畫行為。
BeginTime | 可以用來設(shè)置動畫延遲執(zhí)行時間,若想延遲1s,就設(shè)置為CACurrentMediaTime()+1,CACurrentMediaTime()為圖層的當前時間
巧妙的運用這些可以屬性實現(xiàn)很棒的動畫效果,比如下面:用CABasicAnimation實現(xiàn)的動畫
CABasicAnimation動畫
簡單的呼吸和搖擺動畫

簡單的代碼
1.呼吸動畫
CABasicAnimation *animation =[CABasicAnimation animationWithKeyPath:@"opacity"];
animation.fromValue = [NSNumber numberWithFloat:1.0f];
animation.toValue = [NSNumber numberWithFloat:0.0f];
animation.autoreverses = YES; //回退動畫(動畫可逆,即循環(huán))
animation.duration = 1.0f;
animation.repeatCount = MAXFLOAT;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;//removedOnCompletion,fillMode配合使用保持動畫完成效果
animation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
[self.alphaTagButton.layer addAnimation:animation forKey:@"aAlpha"];
2.搖擺動畫
//設(shè)置旋轉(zhuǎn)原點
self.sharkTagButton.layer.anchorPoint = CGPointMake(0.5, 0);
CABasicAnimation* rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
//角度轉(zhuǎn)弧度(這里用1,-1簡單處理一下)
rotationAnimation.toValue = [NSNumber numberWithFloat:1];
rotationAnimation.fromValue = [NSNumber numberWithFloat:-1];
rotationAnimation.duration = 1.0f;
rotationAnimation.repeatCount = MAXFLOAT;
rotationAnimation.removedOnCompletion = NO;
rotationAnimation.autoreverses = YES;
rotationAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
rotationAnimation.fillMode = kCAFillModeForwards;
[self.sharkTagButton.layer addAnimation:rotationAnimation forKey:@"revItUpAnimation"];
陀螺儀&加速儀的動畫
ps:好吧 這個屬于亂入,和上面的搖擺動畫差不多的效果,只是這個是手動的 哈哈
3、陀螺儀&加速儀的動畫
self.motionManager = [[CMMotionManager alloc] init];
self.motionManager.deviceMotionUpdateInterval = 1.0f/100.0f; //1秒100次
self.sharkTagButton.layer.anchorPoint = CGPointMake(0.5, 0);
[self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMDeviceMotion *motion, NSError *error) {
if(fabs(motion.attitude.roll)<1.0f)
{
[UIView animateWithDuration:0.6 animations:^{
self.sharkTagButton.layer.transform = CATransform3DMakeRotation(-(motion.attitude.roll), 0, 0, 1);
}];
}else if (fabs(motion.attitude.roll)<1.5f)
{
[UIView animateWithDuration:0.6 animations:^{
int s;
if (motion.attitude.roll>0)
{
s=-1;
}else
{
s = 1;
}
self.sharkTagButton.layer.transform = CATransform3DMakeRotation(s*M_PI_2, 0, 0, 1);
}];
}
if ((motion.attitude.pitch)<0)
{
[UIView animateWithDuration:0.6 animations:^{
self.sharkTagButton.layer.transform = CATransform3DMakeRotation(M_PI, 0, 0, 1);
}];
}
}];
Demo地址:
https://github.com/yongliangP/CABasicAnimationDemo
CATransition之簡單的轉(zhuǎn)場動畫
CAAnimation的子類,用于做轉(zhuǎn)場動畫,能夠為層提供移出屏幕和移入屏幕的動畫效果。
| 屬性 | 解讀 |
|---|---|
| type | 動畫過渡類型 |
| subtype | 動畫過渡方向 |
- 常用動畫類型:
| type的值 | 解讀 | 對應(yīng)常量 |
|---|---|---|
| fade | 淡入淡出 | kCATransitionFade |
| push | 推擠 | kCATransitionPush |
| reveal | 揭開 | kCATransitionReveal |
| moveIn | 覆蓋 | kCATransitionMoveIn |
| cube | 立方體 | 私有API |
| suckEffect | 吮吸 | 私有API |
| oglFlip | 翻轉(zhuǎn) | 私有API |
| rippleEffect | 波紋 | 私有API |
| pageCurl | 反翻頁 | 私有API |
| cameraIrisHollowOpen | 開鏡頭 | 私有API |
| cameraIrisHollowClose | 關(guān)鏡頭 | 私有API |
注:私有API只能通過字符串使用哈
- 過渡方向參數(shù):
| subtype的值 | 解讀 |
|---|---|
| kCATransitionFromRight | 從右轉(zhuǎn)場 |
| kCATransitionFromLeft | 從左轉(zhuǎn)場 |
| kCATransitionFromBottom | 從下轉(zhuǎn)場 |
| kCATransitionFromTop | 從上轉(zhuǎn)場 |
簡單的CATransition動畫

-(void)animationWithType:(NSString*)type
{
//- 創(chuàng)建一個轉(zhuǎn)場動畫:
CATransition *transition = [CATransition animation];
transition.repeatCount = 5;
// - 確定動畫類型:
transition.type = type;
// - 確定子類型(方向等)
transition.subtype = kCATransitionFromLeft;
// - 確定動畫時間
transition.duration = 1;
// - 添加動畫
[self.imageView.layer addAnimation:transition forKey:nil];
}
使用時只用傳你的想要的動畫類型就好,私有API只能通過字符串使用哈。
[self animationWithType:self.dataArray[indexPath.row]];
DEMO地址:https://github.com/yongliangP/CATransitionDemo
---20160908更新
CAKeyframeAnimation
先看圖,就是那個在跑的小圓球,為了方便,把動畫集成在了一個Demo里了

- 1 .簡單介紹
CAKeyframeAnimation是CApropertyAnimation的子類,跟CABasicAnimation的區(qū)別是:CABasicAnimation只能從一個數(shù)值(fromValue)變到另一個數(shù)值(toValue),而CAKeyframeAnimation會使用一個NSArray保存這些數(shù)值,是一種更靈活的動畫方式。
- 2 .屬性介紹
| 屬性 | 解讀 |
|---|---|
| values | NSArray對象,里面的元素稱為”關(guān)鍵幀”(keyframe)。動畫對象會在指定的時間(duration)內(nèi),依次顯示values數(shù)組中的每一個關(guān)鍵幀 |
| path | 可以設(shè)置一個CGPathRef\CGMutablePathRef,讓層跟著路徑移動。path只對CALayer的anchorPoint和position起作用。如果你設(shè)置了path,那么values將被忽略 |
| keyTimes | 可以為對應(yīng)的關(guān)鍵幀指定對應(yīng)的時間點,其取值范圍為[0,1],keyTimes中的每一個時間值都對應(yīng)values中的每一幀.當keyTimes沒有設(shè)置的時候,各個關(guān)鍵幀的時間是平分的 |
- 3 .實現(xiàn)
- 3.1 values方式實現(xiàn)
-(void)setUpCAKeyframeAnimationUseValues
{
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"position";
NSValue *value1 = [NSValue valueWithCGPoint:CGPointMake(50, 50)];
NSValue *value2 = [NSValue valueWithCGPoint:CGPointMake(kWindowWidth - 50, 50)];
NSValue *value3 = [NSValue valueWithCGPoint:CGPointMake(kWindowWidth - 50, kWindowHeight-50)];
NSValue *value4 = [NSValue valueWithCGPoint:CGPointMake(50, kWindowHeight-50)];
NSValue *value5 = [NSValue valueWithCGPoint:CGPointMake(50, 50)];
animation.values = @[value1,value2,value3,value4,value5];
animation.repeatCount = MAXFLOAT;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.duration = 6.0f;
animation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[self.keyButton.layer addAnimation:animation forKey:@"values"];
}
- 3.2 path方式實現(xiàn)
-(void)setUpCAKeyframeAnimationUsePath
{
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"position";
CGMutablePathRef path = CGPathCreateMutable();
//矩形線路
CGPathAddRect(path, NULL, CGRectMake(50,50, kWindowWidth - 100,kWindowHeight - 100));
animation.path=path;
CGPathRelease(path);
animation.repeatCount = MAXFLOAT;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.duration = 10.0f;
animation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[self.keyButton.layer addAnimation:animation forKey:@"path"];
}
- 3.3 keyTimes演示
-(void)setUpCAKeyframeAnimationUsekeyTimes
{
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
// animation.keyPath = @"transform.translation.x";
animation.keyPath = @"position.x";
animation.values = @[@0, @20, @-20, @20, @0];
animation.keyTimes = @[ @0, @(1 / 6.0), @(3 / 6.0), @(5 / 6.0), @1 ];
animation.duration = 0.5;
animation.additive = YES;
[self.sharkTagButton.layer addAnimation:animation forKey:@"keyTimes"];
}
---20160921更新
CAAnimationGroup
看圖,就是那個下方的小長方形,簡單實現(xiàn)

動畫組,顧名思義就是動畫的組合,具體動畫可以參考上文,不同的腦洞會出現(xiàn)不同的化學反應(yīng)。
簡單示例:
CABasicAnimation * animationScale = [CABasicAnimation animation];
animationScale.keyPath = @"transform.scale";
animationScale.toValue = @(0.1);
CABasicAnimation *animationRota = [CABasicAnimation animation];
animationRota.keyPath = @"transform.rotation";
animationRota.toValue = @(M_PI_2);
CAAnimationGroup * group = [[CAAnimationGroup alloc] init];
group.duration = 3.0;
group.fillMode = kCAFillModeForwards;
group.removedOnCompletion = NO;
group.repeatCount = MAXFLOAT;
group.animations = @[animationScale,animationRota];
[self.groupButton.layer addAnimation:group forKey:nil];
附:關(guān)于keyPath你可能用到的屬性
| 屬性 | 解讀 |
|---|---|
| transform.rotation.x | 圍繞x軸翻轉(zhuǎn)。y,z同理 參數(shù):角度 |
| transform.rotation | 默認圍繞z軸 |
| transform.scale.x | x方向縮放。y,z同理 |
| transform.scale | 所有方向縮放 |
| transform.translation.x | x軸方向移動,參數(shù):x軸上的坐標。y,z同理 |
| transform.translation | 移動到的點 |
| zPosition | 平面的位置 |
| opacity | 透明度 |
| backgroundColor | 背景顏色 參數(shù):顏色 (id)[[UIColor redColor] CGColor] |
| cornerRadius | layer圓角 |
| borderWidth | 邊框?qū)挾?/td> |
| bounds | 大小 參數(shù):CGRect |
| contents | 內(nèi)容 參數(shù):CGImage |
| contentsRect | 可視內(nèi)容 參數(shù):CGRect 值是0~1之間的小數(shù) |
| position | 位置,效果和transform.rotation差不多 |
| shadowColor | 陰影顏色 |
| shadowOffset | 陰影偏移 |
| shadowOpacity | 陰影透明度 |
| shadowRadius | 陰影角度 |
照例放Demo
Demo地址:
https://github.com/yongliangP/CABasicAnimationDemo
如果你覺得對你有幫助請點喜歡哦,也可以關(guān)注我,每周至少一篇技術(shù)。
或者關(guān)注 我的專題 每周至少5篇更新,多謝支持哈。
(ps:核心動畫編程pdf中文版想要的可以私信我)