在了解核心動(dòng)畫(huà)之前需要先了解CALayer的基本知識(shí),因?yàn)镃AAnimation的實(shí)現(xiàn)是基于CALayer之上。(不了解的童鞋可查閱資料)
CAMediaTiming協(xié)議
CALayer和CAAnimation都遵守CAMediaTiming 協(xié)議,所以CAAnimation在使用過(guò)程中協(xié)議屬性的設(shè)置至關(guān)重要。
CAMediaTiming協(xié)議屬性如下(已做注釋?zhuān)?/p>
@protocol CAMediaTiming
//對(duì)象的開(kāi)始時(shí)間,指動(dòng)畫(huà)開(kāi)始之前的的時(shí)間。默認(rèn)是0.
@property CFTimeInterval beginTime;
//對(duì)象的持續(xù)時(shí)間,默認(rèn)是0.
@property CFTimeInterval duration;
//圖層的比率,用來(lái)衡量最初時(shí)間和當(dāng)前時(shí)間。例如:如果比率為2,當(dāng)前花費(fèi)的時(shí)間就是最初時(shí)間的0.5。默認(rèn)是1。
@property float speed;
/*時(shí)間軸偏移量。將時(shí)間軸移動(dòng)至偏移位置,再執(zhí)行整個(gè)動(dòng)畫(huà)時(shí)長(zhǎng)。假設(shè)動(dòng)畫(huà)時(shí)長(zhǎng)5秒,偏移量為13,
則開(kāi)始位置為13 % 5 = 3,再執(zhí)行一次動(dòng)畫(huà)時(shí)長(zhǎng)5秒,即在時(shí)長(zhǎng)位置3處結(jié)束。*/
@property CFTimeInterval timeOffset;
//重復(fù)次數(shù)
@property float repeatCount;
//對(duì)象的重復(fù)持續(xù)時(shí)間。默認(rèn)是0。
@property CFTimeInterval repeatDuration;
//是否自動(dòng)換向。如果為YES,那么動(dòng)畫(huà)執(zhí)行完會(huì)按照原來(lái)的路徑返回。默認(rèn)是NO。
@property BOOL autoreverses;
/*決定當(dāng)前對(duì)象過(guò)了非active時(shí)間段的行為. 比如動(dòng)畫(huà)開(kāi)始之前、動(dòng)畫(huà)結(jié)束之后。
如果是CAAnimationd對(duì)象,則需要將其removedOnCompletion設(shè)置為NO,要不然fillMode不起作用
*/
@property(copy) NSString *fillMode;
@end
補(bǔ)充:
| fillMode值類(lèi)型 | 注明 |
|---|---|
| kCAFillModeRemoved | 默認(rèn)值。動(dòng)畫(huà)開(kāi)始前和動(dòng)畫(huà)結(jié)束后,動(dòng)畫(huà)對(duì)layer都沒(méi)有影響,動(dòng)畫(huà)結(jié)束后,layer會(huì)恢復(fù)到之前的狀態(tài) |
| kCAFillModeForwards | 動(dòng)畫(huà)結(jié)束后,layer會(huì)一直保持著動(dòng)畫(huà)最后的狀態(tài) |
| kCAFillModeBackwards | 動(dòng)畫(huà)開(kāi)始前,只要將動(dòng)畫(huà)加入了一個(gè)layer,layer便立即進(jìn)入動(dòng)畫(huà)的初始狀態(tài)并等待動(dòng)畫(huà)開(kāi)始 |
| kCAFillModeBoth | 動(dòng)畫(huà)開(kāi)始之前,layer處于動(dòng)畫(huà)初始狀態(tài),動(dòng)畫(huà)結(jié)束后layer保持動(dòng)畫(huà)最后的狀態(tài) |
CAAnimation
CAAnimation主要分為:轉(zhuǎn)場(chǎng)動(dòng)畫(huà)(CATransition)、關(guān)鍵幀動(dòng)畫(huà)(CAKeyframeAnimation)、基本動(dòng)畫(huà)(CABasicAnimation)、組合動(dòng)畫(huà)(CAAnimationGroup)。
(為了更容易看懂每個(gè)動(dòng)畫(huà)之間的關(guān)系,整理了CAAnimation層級(jí)結(jié)構(gòu)圖。)

CAAnimation的屬性以及方法對(duì)繼承自它的四種動(dòng)畫(huà)類(lèi)型是通用的,下面是CAAnimation的屬性列表。
/*速度控制函數(shù)*/
@property(nullable, strong) CAMediaTimingFunction *timingFunction;
/*動(dòng)畫(huà)代理。會(huì)在動(dòng)畫(huà)開(kāi)始和結(jié)束時(shí)調(diào)用對(duì)應(yīng)代理方法。*/
@property(nullable, strong) id <CAAnimationDelegate> delegate;
/*動(dòng)畫(huà)執(zhí)行完畢后是否從圖層上移除。默認(rèn)是YES*/
@property(getter=isRemovedOnCompletion) BOOL removedOnCompletion;
補(bǔ)充:
| timingFunction類(lèi)型 | 注明 |
|---|---|
| kCAMediaTimingFunctionLinear(線性) | 勻速狀態(tài) |
| kCAMediaTimingFunctionEaseIn(漸入) | 緩慢進(jìn)入,然后加速離開(kāi) |
| kCAMediaTimingFunctionEaseOut(漸出) | 全速進(jìn)入,然后減速到達(dá)最終位置 |
| kCAMediaTimingFunctionEaseInEaseOut(漸進(jìn)漸出) | 緩慢進(jìn)入,中間加速,最后減速到達(dá)最終位置。默認(rèn)類(lèi)型 |
下面具體看下每一種動(dòng)畫(huà)類(lèi)型如何使用,以及各自的使用場(chǎng)景。
1、轉(zhuǎn)場(chǎng)動(dòng)畫(huà)(CATransition)
CATransition類(lèi)用來(lái)實(shí)現(xiàn)layer的轉(zhuǎn)場(chǎng)過(guò)渡動(dòng)畫(huà)。
首先需要了解下CATransition的屬性(已做備注)。
@interface CATransition : CAAnimation
/* 過(guò)渡動(dòng)畫(huà)名。當(dāng)前合法的動(dòng)畫(huà)類(lèi)型有:`fade', `moveIn', `push' and `reveal'. 默認(rèn)是`fade'. */
@property(copy) NSString *type;
/* 一個(gè)可選擇的動(dòng)畫(huà)子類(lèi)型. 用來(lái)指定動(dòng)畫(huà)的運(yùn)動(dòng)方向,合法的值是: `fromLeft', `fromRight', `fromTop' and * `fromBottom'. */
@property(nullable, copy) NSString *subtype;
/* 這兩個(gè)屬性用來(lái)控制過(guò)渡動(dòng)畫(huà)的開(kāi)始、結(jié)束執(zhí)行過(guò)程,可以讓動(dòng)畫(huà)停留在某個(gè)動(dòng)畫(huà)點(diǎn)上。合法的值是在0~1范圍內(nèi)。endProgress必須比startProgress的值要大。默認(rèn)值是0—1.
*/
@property float startProgress;
@property float endProgress;
/*filter對(duì)象用來(lái)實(shí)現(xiàn)過(guò)渡動(dòng)畫(huà)。如果設(shè)置了filter,那么為layer設(shè)置的type和subtype屬性將被忽略。*/
@property(nullable, strong) id filter;
@end
補(bǔ)充:
type類(lèi)型還有很多私有API效果,如果代碼中使用的話可能會(huì)導(dǎo)致app審核不通過(guò)。
基本效果
fade //交叉淡化過(guò)渡
push //新視圖把舊視圖推出去
moveIn //新視圖移到舊視圖上面
reveal //將舊視圖移開(kāi),顯示下面的新視圖
私有API:
cube //立方體翻滾效果
oglFlip //上下左右翻轉(zhuǎn)效果
suckEffect //收縮(不支持過(guò)渡方向)
rippleEffect //滴水(不支持過(guò)渡方向)
pageCurl //向上翻頁(yè)
pageUnCurl //向下翻頁(yè)
cameraIrisHollowOpen //相機(jī)鏡頭打開(kāi)(不支持過(guò)渡方向)
cameraIrisHollowClose //相機(jī)鏡頭關(guān)上(不支持過(guò)渡方向)
設(shè)置type的代碼不在此處展示,只需要修改type類(lèi)型即可實(shí)現(xiàn)。下面看下不同type的動(dòng)畫(huà)效果。(因?yàn)間if圖大小限制,所以公有和私有API效果分開(kāi)展示)
基本API運(yùn)行效果:

私有API的運(yùn)行效果如下:

現(xiàn)在通過(guò)代碼實(shí)例來(lái)看一下StartProgress\EndProgress的使用。
注:為了能清楚看出設(shè)置Progress的效果,我把duration時(shí)間設(shè)置為5s。通過(guò)對(duì)比能夠看出來(lái)設(shè)置StartProgress、EndProgress前后的區(qū)別,可根據(jù)自己的實(shí)際需要進(jìn)行設(shè)置。
UILabel * label1 = [[UILabel alloc]init];
label1.backgroundColor = [UIColor lightGrayColor];
label1.text = @"label1";
label1.textColor = [UIColor blackColor];
[self.view addSubview:label1];
UILabel * label2 = [[UILabel alloc]init];
label2.text = @"label2";
label2.backgroundColor = [UIColor lightGrayColor];
label2.textColor = [UIColor blackColor];
[self.view addSubview:label2];
//label1的的動(dòng)畫(huà)
CATransition *animation1 = [CATransition animation];
animation1.duration = 5.0f;
animation1.type = kCATransitionPush;
animation1.subtype = kCATransitionFromBottom;//過(guò)渡方向
[animation1 setStartProgress:0.5];//設(shè)置動(dòng)畫(huà)起點(diǎn)(勻速過(guò)渡動(dòng)畫(huà)路徑的50%處開(kāi)始)
[animation1 setEndProgress:0.8];//設(shè)置動(dòng)畫(huà)終點(diǎn)(勻速過(guò)渡動(dòng)畫(huà)路徑的80%處結(jié)束)
[label1.layer addAnimation:animation1 forKey:@"animation"];
//label2的的動(dòng)畫(huà)
CATransition *animation2 = [CATransition animation];
animation2.duration = 5.0f;
animation2.type = kCATransitionPush;
animation2.subtype = kCATransitionFromBottom;
[label2.layer addAnimation:animation2 forKey:@"animation"];
[label1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(@20);
make.top.equalTo(@180);
make.width.height.mas_equalTo(100);
}];
[label2 mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(@-20);
make.top.equalTo(@180);
make.width.height.mas_equalTo(100);
}];
運(yùn)行結(jié)果如下:

2、基本動(dòng)畫(huà)(CABasicAnimation)
CAPropertyAnimation是通過(guò)animationWithKeyPath方法來(lái)進(jìn)行實(shí)例化的,所以CABasicAnimation、CAKeyframeAnimation都可以通過(guò)animationWithKeyPath的值來(lái)設(shè)定動(dòng)畫(huà)樣式。
animationWithKeyPath常用值如下:
| KeyPath | 效果 |
|---|---|
| transform.scale | 整體比例轉(zhuǎn)換 |
| transform.scale.x | 寬的比例轉(zhuǎn)換 |
| transform.scale.y | 高的比例轉(zhuǎn)換 |
| transform.rotation.x | 圍繞x軸旋轉(zhuǎn) |
| transform.rotation.y | 圍繞y軸旋轉(zhuǎn) |
| transform.rotation.z | 圍繞z軸旋轉(zhuǎn)(平面效果是圍繞中心點(diǎn)旋轉(zhuǎn) ) |
| transform.translation.x | 沿x方向位置移動(dòng) |
| transform.translation.y | 沿y方向位置移動(dòng) |
| transform.translation.z | 沿z方向位置移動(dòng) |
| position | 位置移動(dòng)(關(guān)鍵幀動(dòng)畫(huà)使用時(shí)可以不設(shè)置方向,用貝塞爾曲線繪制路徑) |
| position.x | 沿x方向位置移動(dòng) |
| position.y | 沿y方位置向移動(dòng) |
| position.z | 沿z方向位置移動(dòng) |
| bounds | 坐標(biāo)大小轉(zhuǎn)換 |
| opacity | 改變透明度 |
CABasicAnimation的屬性列表(已做備注):
@interface CABasicAnimation : CAPropertyAnimation
@property(nullable, strong) id fromValue;//所改變屬性的起始值
@property(nullable, strong) id toValue;//所改變屬性的結(jié)束時(shí)的值
@property(nullable, strong) id byValue;//所改變屬性相同起始值的改變量
@end
CABasicAnimation三種動(dòng)畫(huà)方式的實(shí)現(xiàn)代碼示例:
//移動(dòng)動(dòng)畫(huà)
case 0:
{
CABasicAnimation *Animation = [CABasicAnimation animationWithKeyPath:@"position.y"];
Animation.duration = 1.0f;//動(dòng)畫(huà)時(shí)長(zhǎng)
Animation.fromValue = @(imageView.center.y-30);// 起始幀
Animation.toValue = @(imageView.center.y+50);//終止幀
Animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];//速度控制方式:勻速線性
Animation.repeatCount = 1;//重復(fù)次數(shù)
Animation.removedOnCompletion = NO;
Animation.fillMode = kCAFillModeForwards;//動(dòng)畫(huà)結(jié)束后,layer會(huì)一直保持著動(dòng)畫(huà)最后的狀態(tài)
[self.view.layer addAnimation:Animation forKey:@"AnimationMoveY"];
}
break;
//旋轉(zhuǎn)動(dòng)畫(huà):x、y、z三個(gè)方向
case 1:{
CABasicAnimation *Animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];//圍繞Y軸方向旋轉(zhuǎn)
Animation.duration = 1.0f;
Animation.repeatCount = 1;
Animation.fromValue = @(0);
Animation.toValue = @(M_PI);//旋轉(zhuǎn)一周
Animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[imageView.layer addAnimation:Animation forKey:@"RotationY"];
}
break;
// 縮放動(dòng)畫(huà):x、y、z
case 2:{
CABasicAnimation *Animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; // 設(shè)定為縮放
Animation.duration = 1.5f;
Animation.repeatCount = 1;
Animation.autoreverses = YES; // 動(dòng)畫(huà)結(jié)束時(shí)執(zhí)行逆動(dòng)畫(huà),回到起始幀
Animation.fromValue = [NSNumber numberWithFloat:1.0]; // 開(kāi)始時(shí)的倍率
Animation.toValue = [NSNumber numberWithFloat:2.0]; // 結(jié)束時(shí)的倍率
// Animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
// Animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.3, 0.3, 1.0)];
[imageView.layer addAnimation:Animation forKey:@"scale-layer"];
}
break;
//平移動(dòng)畫(huà):必須設(shè)定方向
case 3:{
CABasicAnimation *Animation=[CABasicAnimation animationWithKeyPath:@"transform.translation.y"];
Animation.duration = 1;
Animation.repeatCount = 0;
Animation.removedOnCompletion = FALSE;
Animation.fillMode = kCAFillModeForwards;
Animation.autoreverses = YES;
Animation.fromValue = [NSNumber numberWithFloat:0];
Animation.toValue = [NSNumber numberWithFloat:60];
[self.view.layer addAnimation:Animation forKey:@"animateLayer"];
}
break;
運(yùn)行效果如下:

這只是基本動(dòng)畫(huà)的簡(jiǎn)單實(shí)現(xiàn),稍微復(fù)雜的動(dòng)畫(huà)可以通過(guò)借助組合動(dòng)畫(huà)實(shí)現(xiàn),后面會(huì)有介紹。
3、關(guān)鍵幀動(dòng)畫(huà)(CAKeyframeAnimation)
CAKeyframeAnimation的屬性列表(已做備注)。
@interface CAKeyframeAnimation : CAPropertyAnimation
/*存儲(chǔ)關(guān)鍵幀(keyframe)元素。動(dòng)畫(huà)對(duì)象會(huì)在指定的時(shí)間(duration)內(nèi),依次顯示values數(shù)組中的每一個(gè)關(guān)鍵幀。*/
@property(nullable, copy) NSArray *values;
/*設(shè)置CGPathRef\CGMutablePathRef,讓layer跟著設(shè)定的路徑移動(dòng)。path只對(duì)CALayer的anchorPoint和position起作用。如果設(shè)置了path,values將被忽略。*/
@property(nullable) CGPathRef path;
/*為對(duì)應(yīng)的關(guān)鍵幀指定對(duì)應(yīng)的時(shí)間點(diǎn),其取值范圍為0到1.0,keyTimes中的每一個(gè)時(shí)間值都對(duì)應(yīng)values中的每一幀.當(dāng)keyTimes沒(méi)有設(shè)置的時(shí)候,各個(gè)關(guān)鍵幀的時(shí)間是平均分配的。*/
@property(nullable, copy) NSArray<NSNumber *> *keyTimes;
/*速度控制函數(shù),有kCAMediaTimingFunctionLinear、kCAMediaTimingFunctionEaseIn、kCAMediaTimingFunctionEaseOut、kCAMediaTimingFunctionEaseInEaseOut四種方式,默認(rèn)是最后一種*/
@property(nullable, copy) NSArray<CAMediaTimingFunction *> *timingFunctions
/*計(jì)算模式。主要針對(duì)的是每一幀的內(nèi)容為一個(gè)座標(biāo)點(diǎn)的情況,也就是對(duì)anchorPoint 和 position 進(jìn)行的動(dòng)畫(huà)。
目前提供如下幾種模式:kCAAnimationLinear、kCAAnimationDiscrete 、kCAAnimationPaced
、kCAAnimationCubic 、kCAAnimationCubicPaced。*/
@property(copy) NSString *calculationMode;
/* 該值控制著曲線的緊密度(正值將越緊,負(fù)值將越寬松)*/
@property(nullable, copy) NSArray<NSNumber *> *tensionValues;
/*該值控制片段之間的鏈接(正值將有鋒利的圓角,負(fù)值將是倒立的圓角)*/
@property(nullable, copy) NSArray<NSNumber *> *continuityValues;
/*該值定義了曲線發(fā)生的地點(diǎn)(正值將在控制點(diǎn)前移動(dòng)曲線,負(fù)值將在控制點(diǎn)后移動(dòng))*/
@property(nullable, copy) NSArray<NSNumber *> *biasValues;
/*定義是否沿著路徑旋轉(zhuǎn)匹配對(duì)象動(dòng)畫(huà)路徑切線,值可能為kCAAnimationRotateAuto和kCAAnimationRotateAutoReverse。默認(rèn)是nil。如果沒(méi)有路徑對(duì)象,設(shè)置該屬性值將無(wú)效,kCAAnimationRotateAutoReverse為了匹配正切將添加180°。*/
@property(nullable, copy) NSString *rotationMode;
@end
下面是對(duì)calculationMode的幾種模式的具體注釋?zhuān)?/p>
| calculationMode | 注釋 |
|---|---|
| kCAAnimationLinear | 線性。關(guān)鍵幀為坐標(biāo)點(diǎn)時(shí),直接直線相連進(jìn)行插值計(jì)算。 |
| kCAAnimationDiscrete | 離散不連續(xù)的。只展示關(guān)鍵幀的狀態(tài),沒(méi)有中間過(guò)程,沒(méi)有動(dòng)畫(huà)。 |
| kCAAnimationPaced | 節(jié)奏。動(dòng)畫(huà)均勻進(jìn)行,不按keyTimes設(shè)置的或者按關(guān)鍵幀平分時(shí)間,所以keyTimes和timingFunctions無(wú)效 |
| kCAAnimationCubic | 以關(guān)鍵幀為坐標(biāo)點(diǎn)進(jìn)行圓滑曲線相連后插值計(jì)算,目的是使得運(yùn)行的軌跡變得圓滑。對(duì)于曲線的形狀還可以通過(guò)tensionValues、continuityValues、biasValues進(jìn)行調(diào)整自定義 |
| kCAAnimationCubicPaced | 在kCAAnimationCubic的基礎(chǔ)上使動(dòng)畫(huà)變得均勻,就是系統(tǒng)時(shí)間內(nèi)運(yùn)動(dòng)的距離相同。如果設(shè)定的話keyTimes、timingFunctions無(wú)效。 |
注:
CAKeyframeAnimation和CABasicAnimation都是CApropertyAnimation的子類(lèi),區(qū)別是:CABasicAnimation只能從一個(gè)數(shù)值(fromValue)變到另一個(gè)數(shù)值(toValue),而CAKeyframeAnimation可以使用values保存這些數(shù)值,但是CAKeyframeAnimation的實(shí)現(xiàn)方式也不止values,還有path。
實(shí)現(xiàn)關(guān)鍵幀動(dòng)畫(huà)兩種方式的代碼示例(values和path):
-(void)AnimationClick:(UIButton *)button{
switch (button.tag) {
//Values實(shí)現(xiàn)
case 0:
{
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
//動(dòng)畫(huà)路徑的values
NSValue *value1=[NSValue valueWithCGPoint:CGPointMake(100, 250)];
NSValue *value2=[NSValue valueWithCGPoint:CGPointMake(200, 250)];
NSValue *value3=[NSValue valueWithCGPoint:CGPointMake(200, 300)];
NSValue *value4=[NSValue valueWithCGPoint:CGPointMake(100, 300)];
NSValue *value5=[NSValue valueWithCGPoint:CGPointMake(100, 400)];
NSValue *value6=[NSValue valueWithCGPoint:CGPointMake(200, 400)];
animation.values=@[value1,value2,value3,value4,value5,value6];
//重復(fù)次數(shù)
animation.repeatCount=MAXFLOAT;
//設(shè)置是否原路返回
animation.autoreverses = YES;
//設(shè)置移動(dòng)速度,越小越快
animation.duration = 4.0f;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[imageView.layer addAnimation:animation forKey:nil];
}
break;
//通過(guò)Path方式
case 1:{
//創(chuàng)建動(dòng)畫(huà)對(duì)象
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
//創(chuàng)建一個(gè)CGPathRef對(duì)象,就是動(dòng)畫(huà)的路線
CGMutablePathRef path = CGPathCreateMutable();
//設(shè)置開(kāi)始位置
CGPathMoveToPoint(path,NULL,100,250);
//沿直線移動(dòng)
CGPathAddLineToPoint(path,NULL, 200, 250);
CGPathAddLineToPoint(path,NULL, 200, 300);
CGPathAddLineToPoint(path,NULL, 100, 300);
CGPathAddLineToPoint(path,NULL, 100, 400);
CGPathAddLineToPoint(path,NULL, 200, 400);
//沿著曲線移動(dòng)
CGPathAddCurveToPoint(path,NULL,200.0,500.0,250.0,500.0,250.0,400.0);
CGPathAddCurveToPoint(path,NULL,250.0,500.0,300.0,500.0,300.0,400.0);
//自動(dòng)沿著弧度移動(dòng)
CGPathAddEllipseInRect(path, NULL, CGRectMake(300, 400, 70, 70));
animation.path=path;
CGPathRelease(path);
animation.autoreverses = YES;
animation.repeatCount=1;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.duration = 8.0f;
animation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[imageView.layer addAnimation:animation forKey:nil];
//繪制出動(dòng)畫(huà)路徑,方便觀察
CAShapeLayer *line = [[CAShapeLayer alloc]init];
line.fillColor = [UIColor clearColor].CGColor;
line.borderWidth = 1;
line.strokeColor = [UIColor redColor].CGColor;
line.path = path;
[self.view.layer addSublayer:line];
}
break;
default:
break;
}
}
運(yùn)行結(jié)果如下:

4、組合動(dòng)畫(huà)(CAAnimationGroup)
CAAnimationGroup只有一個(gè)屬性animations。
@interface CAAnimationGroup : CAAnimation
/* 存儲(chǔ)CAAnimation對(duì)象的數(shù)組。數(shù)組的每一個(gè)元素在規(guī)定的duration時(shí)間內(nèi)同時(shí)進(jìn)行。*/
@property(nullable, copy) NSArray<CAAnimation *> *animations;
@end
做一個(gè)簡(jiǎn)單的加入購(gòu)物車(chē)動(dòng)畫(huà)。代碼如下::
//貝塞爾曲線路徑
UIBezierPath *movePath = [UIBezierPath bezierPath];
[movePath moveToPoint:CGPointMake(0.0, 64.0)];
[movePath addQuadCurveToPoint:CGPointMake(300, 400) controlPoint:CGPointMake(200, 100)];
//關(guān)鍵幀動(dòng)畫(huà)(設(shè)置位置)
CAKeyframeAnimation * posAnim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
posAnim.path = movePath.CGPath;
//縮放動(dòng)畫(huà)
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
scaleAnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
scaleAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.3, 0.3, 1.0)];
//旋轉(zhuǎn)動(dòng)畫(huà)
CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];//圍繞Y軸方向旋轉(zhuǎn)
rotationAnimation.duration = 0.2;
rotationAnimation.repeatCount = MAXFLOAT;
rotationAnimation.fromValue = @(0);
rotationAnimation.toValue = @(M_PI);//旋轉(zhuǎn)一周
//透明度動(dòng)畫(huà)
CABasicAnimation *opacityAnim = [CABasicAnimation animationWithKeyPath:@"opacity"];
opacityAnim.fromValue = [NSNumber numberWithFloat:1.0];
opacityAnim.toValue = [NSNumber numberWithFloat:0.6];
//動(dòng)畫(huà)組
CAAnimationGroup *animGroup = [CAAnimationGroup animation];
animGroup.animations = [NSArray arrayWithObjects:posAnim, scaleAnimation,rotationAnimation, opacityAnim,nil];
animGroup.duration = 1;
animGroup.autoreverses = NO;
animGroup.fillMode = kCAFillModeForwards;
[goodsView.layer addAnimation:animGroup forKey:nil];
運(yùn)行效果:
