1. 簡介
- Core Animation 中文翻譯為核心動畫徘郭,它是一組非常強(qiáng)大的動畫處理API赶促,使用它能做出非常炫麗的動畫效果好芭,而且往往是事半功倍承疲。也就是說,使用少量的代碼就可以實(shí)現(xiàn)非常強(qiáng)大的功能鸥咖。
- Core Animation的動畫執(zhí)行過程都是在后臺操作的燕鸽,不會阻塞主線程,即動畫的時候可以點(diǎn)擊(按鈕)。
- Core Animation是直接作用在CALayer上的啼辣,并非UIView
2. 核心動畫類的層次結(jié)構(gòu)
核心動畫位于CAAnimation.h中啊研,該文件提供了以下接口及類層級結(jié)構(gòu)
如上圖所示,CoreAnimation所使用類如下:
CAMediaTiming:CAAnimation實(shí)現(xiàn)的協(xié)議鸥拧,共有8個屬性控制動畫的過程党远;
CAAnimation:該類是所有動畫的抽象類,不能直接使用富弦,只能使用其子類沟娱。并且實(shí)現(xiàn)了CAMediaTiming協(xié)議;
CAPropertyAnimation:是CAAnimation的子類腕柜,支持動畫
CABasicAnimation:基本動畫-
CATransition:轉(zhuǎn)場動畫
CAKeyframeAnimation:關(guān)鍵幀動畫
CAAnimationGroup:組動畫
CASpringAnimation:彈簧動畫
3. CAMediaTiming協(xié)議
CAMediaTiming協(xié)議共有8個屬性济似,每個屬性簡單介紹如下
屬性 | 說明 |
---|---|
duration | 動畫持續(xù)時間 |
beginTime | 動畫相對一個對象開始的時間,起到延時執(zhí)行的目的 |
speed | 動畫執(zhí)行速度 |
timeOffset | 動畫執(zhí)行偏移 |
repeatCount | 動畫執(zhí)行重復(fù)次數(shù) |
repeatDuration | 動畫執(zhí)行時間 |
autoreverses | 動畫結(jié)束后是否反向執(zhí)行 |
fillMode | 決定當(dāng)前對象在非active時間段的行為 |
3.1. duration
代碼如下:
#import "ViewController.h"
#define kScreenW ([UIScreen mainScreen].bounds.size.width)
#define kScreenH ([UIScreen mainScreen].bounds.size.height)
@interface ViewController ()
@property (nonatomic,weak) CALayer *redLayer;
@property (nonatomic,weak) CALayer *blueLayer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//1 添加一個紅色的Layer
CALayer *redLayer = [CALayer layer];
self.redLayer = redLayer;
redLayer.backgroundColor = [UIColor redColor].CGColor;
redLayer.frame = CGRectMake(0, 0, kScreenW/2.0, 50);
[self.view.layer addSublayer:redLayer];
//1 添加一個藍(lán)色的Layer
CALayer *blueLayer =[CALayer layer];
self.blueLayer = blueLayer;
blueLayer.backgroundColor =[UIColor blueColor].CGColor;
blueLayer.frame = CGRectMake(kScreenW/2.0, 0, kScreenW/2.0, 50);
[self.view.layer addSublayer:blueLayer];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//給紅色Layer添加動畫
CABasicAnimation *redLayerBasicAnimation = [CABasicAnimation animation];
redLayerBasicAnimation.keyPath=@"position";
redLayerBasicAnimation.fromValue=[NSValue valueWithCGPoint:self.redLayer.position];
redLayerBasicAnimation.toValue=[NSValue valueWithCGPoint:CGPointMake(self.redLayer.position.x, kScreenH)];
//設(shè)置動畫持續(xù)時間
redLayerBasicAnimation.duration = 10;
[self.redLayer addAnimation:redLayerBasicAnimation forKey:nil];
//給藍(lán)色Layer添加動畫
CABasicAnimation *blueLayerBasicAnimation = [CABasicAnimation animation];
blueLayerBasicAnimation.keyPath=@"position";
blueLayerBasicAnimation.fromValue=[NSValue valueWithCGPoint:self.blueLayer.position];
blueLayerBasicAnimation.toValue=[NSValue valueWithCGPoint:CGPointMake(self.blueLayer.position.x, kScreenH)];
//設(shè)置動畫持續(xù)時間
blueLayerBasicAnimation.duration = 5;
[self.blueLayer addAnimation:blueLayerBasicAnimation forKey:nil];
}
@end
上述代碼在視圖上添加兩個動畫盏缤,其中一個動畫持續(xù)10s砰蠢,另一個動畫持續(xù)5秒,豎向位移為屏幕高
執(zhí)行效果如下
3.2. beginTime
beginTime為相對時間系開始的時間唉铜,可以認(rèn)為是起到延時左右,設(shè)置右側(cè)藍(lán)色Layer相對當(dāng)前時間系延時5s時間執(zhí)行
//相對于當(dāng)前時間系延后5秒台舱,起到延時作用
blueLayerBasicAnimation.beginTime = CACurrentMediaTime()+5;
執(zhí)行效果顯示藍(lán)色相對紅色延時5秒后執(zhí)行,且同時到達(dá)底
端
3.3. speed
speed為相對一個時間系打毛,本Layer時間流逝速度柿赊,默認(rèn)情況為1,設(shè)置藍(lán)色Layer時間流逝速度為0.5倍則在不設(shè)置時間偏移的情況下兩者同時到達(dá)低端幻枉,效果如下:
3.4. timeOffset
該屬性主要標(biāo)記一個動畫從何處執(zhí)行碰声,該屬性不存在延遲作用。例如一個動畫正常執(zhí)行如下順序:
A --> B --> C --> D --> A
此時如果設(shè)置 timeOffset 為B狀態(tài)熬甫,則該動畫開始執(zhí)行狀態(tài)為
B --> C --> D --> A --> B
設(shè)置紅色動畫持續(xù)時間10s胰挑,藍(lán)色動畫持續(xù)時間5秒,設(shè)置藍(lán)色動畫的timeOffset為2.5秒
//相對于當(dāng)前時間系延后5秒椿肩,起到延時作用
//blueLayerBasicAnimation.beginTime = CACurrentMediaTime()+5;
//設(shè)置時間流逝速度
//blueLayerBasicAnimation.speed = 0.5;
//設(shè)置動畫偏移時間
blueLayerBasicAnimation.timeOffset =CACurrentMediaTime()+2.5;
運(yùn)行效果如下:
3.5. repeatCount
repeatCount該屬性主要記錄動畫重復(fù)持續(xù)次數(shù)瞻颂,設(shè)定紅色Layer動畫持續(xù)時間為10s,藍(lán)色為5s,新添加藍(lán)色Layer重復(fù)次數(shù)為2次,代碼如下:
blueLayerBasicAnimation.duration = 5;
//相對于當(dāng)前時間系延后5秒郑象,起到延時作用
//blueLayerBasicAnimation.beginTime = CACurrentMediaTime()+5;
//設(shè)置時間流逝速度
//blueLayerBasicAnimation.speed = 0.5;
//設(shè)置動畫偏移時間
//blueLayerBasicAnimation.timeOffset =CACurrentMediaTime()+2.5;
//設(shè)置動畫重復(fù)次數(shù)
blueLayerBasicAnimation.repeatCount = 2;
效果如下:
3.6. repeatDuration
repeatDuration該屬性主要記錄動畫重復(fù)持續(xù)時間贡这,設(shè)定紅色Layer動畫持續(xù)時間為10s,藍(lán)色為5s,新添加藍(lán)色Layer動畫持續(xù)時間12.5秒,代碼如下:
blueLayerBasicAnimation.duration = 5;
//相對于當(dāng)前時間系延后5秒厂榛,起到延時作用
//blueLayerBasicAnimation.beginTime = CACurrentMediaTime()+5;
//設(shè)置時間流逝速度
//blueLayerBasicAnimation.speed = 0.5;
//設(shè)置動畫偏移時間
//blueLayerBasicAnimation.timeOffset =CACurrentMediaTime()+2.5;
//設(shè)置動畫重復(fù)次數(shù)
//blueLayerBasicAnimation.repeatCount = 2;
//設(shè)置動畫持續(xù)時間
blueLayerBasicAnimation.repeatDuration = 12.5;
運(yùn)行效果如下:
3.7. autoreverses
該屬性主要執(zhí)行結(jié)束動畫后是否執(zhí)行逆行動畫過程盖矫,默認(rèn)NO不執(zhí)行丽惭,如果YES則執(zhí)行,
blueLayerBasicAnimation.duration = 5;
//相對于當(dāng)前時間系延后5秒辈双,起到延時作用
//blueLayerBasicAnimation.beginTime = CACurrentMediaTime()+5;
//設(shè)置時間流逝速度
//blueLayerBasicAnimation.speed = 0.5;
//設(shè)置動畫偏移時間
//blueLayerBasicAnimation.timeOffset =CACurrentMediaTime()+2.5;
//設(shè)置動畫重復(fù)次數(shù)
//blueLayerBasicAnimation.repeatCount = 2;
//設(shè)置動畫持續(xù)時間
//blueLayerBasicAnimation.repeatDuration = 12.5;
//動畫
blueLayerBasicAnimation.autoreverses = YES;
3.8. fillMode
fillMode決定當(dāng)前對象在非active時間段的行為.比如動畫開始之前,動畫結(jié)束之后 责掏,但是該屬性要和CAAnimation中的removedOnCompletion屬性配合著使用.
/* When true, the animation is removed from the render tree once its
* active duration has passed. Defaults to YES. */
如果是true,一旦動畫的活動期間過了湃望,那么這個動畫將被移除换衬,默認(rèn)值YES
@property(getter=isRemovedOnCompletion) BOOL removedOnCompletion;
其中fillMode屬性值(要想fillMode有效,最好設(shè)置removedOnCompletion=NO)存在四中狀態(tài)证芭,如下:
/* `fillMode' options. */
CA_EXTERN NSString * const kCAFillModeForwards
__OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);
CA_EXTERN NSString * const kCAFillModeBackwards
__OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);
CA_EXTERN NSString * const kCAFillModeBoth
__OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);
CA_EXTERN NSString * const kCAFillModeRemoved
__OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);
- ** kCAFillModeForwards** :當(dāng)動畫結(jié)束后,layer會保持在動畫結(jié)束狀態(tài).
- ** kCAFillModeBackwards** :當(dāng)動畫結(jié)束后,layer會一直保持著動畫最后的狀態(tài).
- ** kCAFillModeBoth** :這個其實(shí)就是上面兩個的合成.動畫加入后開始之前,layer便處于動畫初始狀態(tài),動畫結(jié)束后layer保持動畫最后的狀
- ** kCAFillModeRemoved** :這個是默認(rèn)值,也就是說當(dāng)動畫開始前和動畫結(jié)束后,動畫對layer都沒有影響,動畫結(jié)束后,layer會恢復(fù)到之前的狀態(tài)
測試kCAFillModeForwards狀態(tài)代碼如下:
blueLayerBasicAnimation.fillMode = kCAFillModeForwards;
blueLayerBasicAnimation.removedOnCompletion = NO;
運(yùn)行效果如下:
4.0 CAAnimation抽象類
CAAnimation是Core Animation所有動畫類型的抽象基類瞳浦。作為一個抽象類,CAAnimation本身并沒有做多少工作檩帐,它提供了一個計(jì)時函數(shù)(用于動畫的進(jìn)入進(jìn)出狀態(tài))术幔,一個委托(用于反饋動畫狀態(tài))以及一個removedOnCompletion,用于標(biāo)識動畫是否該在結(jié)束后自動釋放(默認(rèn)YES湃密,為了防止內(nèi)存泄露)。CAAnimation同時實(shí)現(xiàn)了一些協(xié)議四敞,包括CAMediaTiming泛源。
/* Creates a new animation object. */
+ (instancetype)animation;
/* Animations implement the same property model as defined by CALayer.
* See CALayer.h for more details. */
+ (nullable id)defaultValueForKey:(NSString *)key;
- (BOOL)shouldArchiveValueForKey:(NSString *)key;
/* A timing function defining the pacing of the animation. Defaults to
* nil indicating linear pacing. */
@property(nullable, strong) CAMediaTimingFunction *timingFunction;
/* The delegate of the animation. This object is retained for the
* lifetime of the animation object. Defaults to nil. See below for the
* supported delegate methods. */
@property(nullable, strong) id delegate;
/* When true, the animation is removed from the render tree once its
* active duration has passed. Defaults to YES. */
@property(getter=isRemovedOnCompletion) BOOL removedOnCompletion;
4.1. +animation方法
該方法為抽象方法,由子類創(chuàng)建實(shí)例對象忿危,生成相應(yīng)的對象類型达箍。例如基本動畫、關(guān)鍵幀動畫铺厨、組動畫缎玫、轉(zhuǎn)場動畫。
4.2. timingFunction屬性
摘錄參考blog
Timing Function的會被用于變化起點(diǎn)和終點(diǎn)之間的插值計(jì)算.形象點(diǎn)說是Timing Function決定了動畫運(yùn)行的節(jié)奏(Pacing),比如是均勻變化(線性變化)解滓、先快后慢赃磨、先慢后快、還是先慢再快再慢.
時間函數(shù)是使用的一段函數(shù)來描述的,橫座標(biāo)是時間t取值范圍是0.0-1.0,縱座標(biāo)是變化量x(t)也是取值范圍也是0.0-1.0 假設(shè)有一個動畫,duration是8秒,變化值的起點(diǎn)是a終點(diǎn)是b(假設(shè)是透明度),那么在4秒處的值是多少呢洼裤? 可以通過計(jì)算為 a + x(4/8) * (b-a), 為什么這么計(jì)算呢邻辉?講實(shí)現(xiàn)的時間映射到單位值的時候4秒相對于總時間8秒就是0.5然后可以得到0.5的時候單位變化量是 x(0.5), x(0.5)/1 = 實(shí)際變化量/(b-a), 其中b-a為總變化量,所以實(shí)際變化量就是x(0.5) * (b-a) ,最后4秒時的值就是 a + x(0.5) * (b-a),所以計(jì)算的本質(zhì)是映射
Timing Function對應(yīng)的類是CAMediaTimingFunction,它提供了兩種獲得時間函數(shù)的方式,一種是使用預(yù)定義的五種時間函數(shù),一種是通過給點(diǎn)兩個控制點(diǎn)得到一個時間函數(shù). 相關(guān)的方法為
+ (instancetype)functionWithName:(NSString *)name;
+ (instancetype)functionWithControlPoints:(float)c1x :(float)c1y :(float)c2x :(float)c2y;
- (instancetype)initWithControlPoints:(float)c1x :(float)c1y :(float)c2x :(float)c2y;
- (void)getControlPointAtIndex:(size_t)idx values:(float[2])ptr;
五種預(yù)定義的時間函數(shù)名字的常量變量分別為
- ** ** kCAMediaTimingFunctionLinear,
- ** **kCAMediaTimingFunctionEaseIn,
- ** **kCAMediaTimingFunctionEaseOut,
- ** **kCAMediaTimingFunctionEaseInEaseOut,
- ** **kCAMediaTimingFunctionDefault.
下圖展示了前面四種Timing Function的曲線圖,橫座標(biāo)表示時間,縱座標(biāo)表示變化量,這點(diǎn)需要搞清楚(并不是平面座標(biāo)系中xy).
自定義的Timing Function的函數(shù)圖像就是一條三次貝塞爾曲線Cubic Bezier Curve,貝塞爾曲線的優(yōu)點(diǎn)就是光滑,用在這里就使得變化顯得光滑.一條三次貝塞爾曲線可以由起點(diǎn)終點(diǎn)以及兩個控制點(diǎn)決定.
上面的kCAMediaTimingFunctionDefault對應(yīng)的函數(shù)曲線其實(shí)就是通過[(0.0,0.0), (0.25,0.1), (0.25,0.1), (1.0,1.0)]這四個點(diǎn)決定的三次貝塞爾曲線,頭尾為起點(diǎn)和終點(diǎn),中間的兩個點(diǎn)是控制點(diǎn).
上圖中P0是起點(diǎn),P3是終點(diǎn),P1和P2是兩個控制點(diǎn)
4.3. delegate代理屬性
CAAnimation提供代理協(xié)議,代理方法提供了動畫開始和動畫結(jié)束方法腮鞍,通過代理方法執(zhí)行回調(diào)值骇。
@interface NSObject (CAAnimationDelegate)
/* Called when the animation begins its active duration. */
- (void)animationDidStart:(CAAnimation *)anim;
/* Called when the animation either completes its active duration or
* is removed from the object it is attached to (i.e. the layer). 'flag'
* is true if the animation reached the end of its active duration
* without being removed. */
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
@end
4.4. removedOnCompletion
該方法前邊已經(jīng)介紹,用于移除動畫使用
5.0. CAPropertyAnimation
CAPropertyAnimation也是個抽象類移国,本身不具備動畫效果吱瘩,只有子類才有,主要存在以下方法和屬性
@interface CAPropertyAnimation : CAAnimation
+ (instancetype)animationWithKeyPath:(nullable NSString *)path;
@property(nullable, copy) NSString *keyPath;
@property(getter=isAdditive) BOOL additive;
@property(getter=isCumulative) BOOL cumulative;
@property(nullable, strong) CAValueFunction *valueFunction;
@end
6.0 CABasicAnimation基礎(chǔ)動畫
CABasicAnimation 基礎(chǔ)動畫其實(shí)就是一段時間內(nèi)發(fā)生的改變,最簡單的形式就是從一個值改變到另一個值迹缀,
@property(nullable, strong) id fromValue;
@property(nullable, strong) id toValue;
@property(nullable, strong) id byValue;
下面這段英文摘自蘋果官方文檔使碾,將的是fromValue toValue ByValue 怎么使用
The interpolation values are used as follows:
** **Both fromValue and toValue are non-nil. Interpolates between fromValue and toValue.
翻譯:fromValue和toValue都不為空蜜徽,在fromValue到toValue之間插值** **fromValue and byValue are non-nil. Interpolates between fromValue and (fromValue + byValue).
翻譯:fromValue和byValue都不為空漱逸,在fromValue到fromValue +byValue之間插值** **byValue and toValue are non-nil. Interpolates between (toValue - byValue) and toValue.
翻譯:byValue和toValue都不為空团秽,在 (toValue - byValue) 到toValue之間插值** **fromValue is non-nil. Interpolates between fromValue and the current presentation value of the property.
翻譯:fromValue不為空架诞,在 fromValue到對象當(dāng)前值之間插值** **toValue is non-nil. Interpolates between the current value of keyPath in the target layer’s presentation layer andtoValue.
翻譯:toValue不為空匠抗,在 對象當(dāng)前值到toValue之間插值** **byValue is non-nil. Interpolates between the current value of keyPath in the target layer’s presentation layer and that value plus byValue.
翻譯:byValue不為空耸采,在 對象當(dāng)前值到經(jīng)過byValue值之間插值** **All properties are nil. Interpolates between
the previous value of keyPath in the target layer’s presentation layer and
the current value of keyPath in the target layer’s presentation layer.
翻譯:都不為空锣杂,在 對象以前值到對象當(dāng)前值之間插值(不懂)
7. CAKeyframeAnimation關(guān)鍵幀動畫
CAKeyframeAnimation 關(guān)鍵幀動畫未玻,該動畫從字面簡單的理解為做動畫時只需要給出動畫部分關(guān)鍵幀即可辉浦,系統(tǒng)會通過插值方式自己完成動畫颅和,在文件中存在以屬性:
/** General keyframe animation class. **/
@interface CAKeyframeAnimation : CAPropertyAnimation
@property(nullable, copy) NSArray *values;
@property(nullable) CGPathRef path;
@property(nullable, copy) NSArray<NSNumber *> *keyTimes;
@property(nullable, copy) NSArray<CAMediaTimingFunction *> *timingFunctions;
@property(copy) NSString *calculationMode;
@property(nullable, copy) NSArray<NSNumber *> *tensionValues;
@property(nullable, copy) NSArray<NSNumber *> *continuityValues;
@property(nullable, copy) NSArray<NSNumber *> *biasValues;
@property(nullable, copy) NSString *rotationMode;
@end
7.1 values屬性
values屬性為NSArray類型傅事,里面的元素稱為“關(guān)鍵幀”(keyframe)。動畫對象會在指定的時間(duration)內(nèi)峡扩,依次顯示values數(shù)組中的每一個關(guān)鍵幀
代碼如下:
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"position.y";
animation.values = @[@150,@400,@100,@400];
animation.duration = 5.f;
[self.testLayer addAnimation:animation forKey:nil];
執(zhí)行動畫效果:
7.2 keyTimes屬性
keyTimes可以為對應(yīng)的關(guān)鍵幀指定對應(yīng)的時間點(diǎn)蹭越,其取值范圍為0~1.0,keyTimes中的每一個時間值都對應(yīng)values中的每一幀教届。如果沒有設(shè)置keyTimes响鹃,各個關(guān)鍵幀的時間是平分的
keyTimes值要和運(yùn)行時間段吻合,如果不吻合會出現(xiàn)以下問題:
第一種情況:吻合情況
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"position.y";
animation.values = @[@400,@0,@400,@0];//定義了4幀
animation.duration = 5.f;
//設(shè)置每一個關(guān)鍵幀的時間
animation.keyTimes = @[@0,@(1/8.),@(3/8.),@1];
[self.testLayer addAnimation:animation forKey:nil];
效果如下:
分析:
添加keyTimes記錄著執(zhí)行到每一幀動畫的時間點(diǎn)案训,例如:
@400 @0 為起始值
@400 - > @0過程中买置,必須在@(1/8.)執(zhí)行到@0位置
@0 - >@400過程中,必須在@(3/8.)執(zhí)行到@ 400位置
@400 - > @0過程中强霎,必須在@1執(zhí)行到@0位置
第二種情況:少給值了忿项,少給則提前結(jié)束
//設(shè)置每一個關(guān)鍵幀的時間
animation.keyTimes = @[@0,@(1/8.),@1];
運(yùn)行效果:
分析:
添加keyTimes記錄著執(zhí)行到每一幀動畫的時間點(diǎn),例如:
@400 @0 為起始值
@400 - > @0過程中城舞,必須在@(1/8.)執(zhí)行到@0位置
@0 - >@400過程中轩触,必須在@(1)執(zhí)行到@ 400位置,由于@1時間結(jié)束家夺,所以動畫直接結(jié)束
第三種情況:多給值了脱柱,則按照順序執(zhí)行,剩余時間無效
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"position.y";
animation.values = @[@400,@0,@400,@0];//定義了4幀
animation.duration = 5.f;
//設(shè)置每一個關(guān)鍵幀的時間
animation.keyTimes = @[@0,@(1/8.),@(2/8.),@(3/8.),@(4/8.),@1];
[self.testLayer addAnimation:animation forKey:nil];
效果:
分析:
添加keyTimes記錄著執(zhí)行到每一幀動畫的時間點(diǎn)秦踪,例如:
@400 @0 為起始值
@400 - > @0過程中褐捻,必須在@(1/8.)執(zhí)行到@0位置
@0 - >@400過程中,必須在@(2/8.)執(zhí)行到@ 400位置
@400 - > @0過程中椅邓,必須在@@(3/8.)執(zhí)行到@0位置
剩余時間@(3/8.) -> @1這個時間段屬于無效冗余時間柠逞,所以動畫在等待到@1這一時刻立即結(jié)束。
7.3. timingFunctions
該屬性在上述已經(jīng)介紹過了景馁,只不過是在動畫每一個執(zhí)行路徑過程中執(zhí)行的時間類型函數(shù),如果你values個數(shù)為N板壮,則timingFunctions 個數(shù)至少為N-1;否則剩余部分則執(zhí)行線性時間函數(shù)合住。
代碼例子:
animation.timingFunctions = @[
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
運(yùn)行效果:
7.4. calculationMode屬性
在關(guān)鍵幀動畫中還有一個非常重要的參數(shù),那便是calculationMode,計(jì)算模式.其主要針對的是每一幀的內(nèi)容為一個座標(biāo)點(diǎn)的情況,也就是對anchorPoint 和 position 進(jìn)行的動畫.當(dāng)在平面座標(biāo)系中有多個離散的點(diǎn)的時候,可以是離散的,也可以直線相連后進(jìn)行插值計(jì)算,也可以使用圓滑的曲線將他們相連后進(jìn)行插值計(jì)算. calculationMode目前提供如下幾種模式 kCAAnimationLinear
- ** kCAAnimationLinear :** calculationMode的默認(rèn)值,表示當(dāng)關(guān)鍵幀為座標(biāo)點(diǎn)的時候,關(guān)鍵幀之間直接直線相連進(jìn)行插值計(jì)算;
- ** kCAAnimationDiscrete ** 離散的,就是不進(jìn)行插值計(jì)算,所有關(guān)鍵幀直接逐個進(jìn)行顯示;
- ** kCAAnimationPaced ** 使得動畫均勻進(jìn)行,而不是按keyTimes設(shè)置的或者按關(guān)鍵幀平分時間,此時keyTimes和timingFunctions無效;
- ** kCAAnimationCubic ** 對關(guān)鍵幀為座標(biāo)點(diǎn)的關(guān)鍵幀進(jìn)行圓滑曲線相連后插值計(jì)算,對于曲線的形狀還可以通過tensionValues,continuityValues,biasValues來進(jìn)行調(diào)整自定義,這里的數(shù)學(xué)原理是Kochanek–Bartels spline,這里的主要目的是使得運(yùn)行的軌跡變得圓滑;
- ** kCAAnimationCubicPaced ** 看這個名字就知道和kCAAnimationCubic有一定聯(lián)系,其實(shí)就是在kCAAnimationCubic的基礎(chǔ)上使得動畫運(yùn)行變得均勻,就是系統(tǒng)時間內(nèi)運(yùn)動的距離相同,此時keyTimes以及timingFunctions也是無效的.
對于這五種效果分別如下
8. CAAnimationGroup組動畫
組動畫绰精,比較簡單為兩個動畫的結(jié)合體
@interface CAAnimationGroup : CAAnimation
@property(nullable, copy) NSArray<CAAnimation *> *animations;
@end
代碼如下:
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic,weak) CALayer *myLayer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
CALayer *myLayer=[[CALayer alloc] init];
self.myLayer=myLayer;
myLayer.bounds=CGRectMake(0, 0, 100, 30);
myLayer.position=CGPointMake(200, 200);
myLayer.backgroundColor=[UIColor redColor].CGColor;
[self.view.layer addSublayer:myLayer];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
//第一組動畫
CAKeyframeAnimation *keyframe=[CAKeyframeAnimation animationWithKeyPath:nil];
keyframe.keyPath=@"position";
UIBezierPath *path=[UIBezierPath bezierPathWithArcCenter:CGPointMake(200 , 200) radius:150 startAngle:0 endAngle:2*M_PI clockwise:YES];
keyframe.path=path.CGPath;
//第二組
CABasicAnimation *basic=[CABasicAnimation animationWithKeyPath:nil];
basic.keyPath=@"transform.rotation";
basic.byValue=@(2*M_PI *20);
//把兩組動畫組成組動畫
CAAnimationGroup *group=[[CAAnimationGroup alloc] init];
group.duration=10;
group.repeatCount=INT16_MAX;
group.animations=@[keyframe,basic];
[self.myLayer addAnimation:group forKey:nil];
}
@end
運(yùn)行效果:
9. CATransition轉(zhuǎn)場動畫
/** Transition animation subclass. **/
@interface CATransition : CAAnimation
@property(copy) NSString *type;
@property(nullable, copy) NSString *subtype;
@property float startProgress;
@property float endProgress;
@property(nullable, strong) id filter;
@end
9.1 type動畫過渡類型
主要提供了4中過渡方式
- ** kCATransitionFade**交叉淡化過渡(不支持過渡方向)
- ** kCATransitionMoveIn**新視圖移到舊視圖上面
- ** kCATransitionPush**新視圖把舊視圖推出去
- ** kCATransitionReveal**將舊視圖移開,顯示下面的新視圖
私有API
- cube //立方體翻滾效果
- oglFlip //上下左右翻轉(zhuǎn)效果
- suckEffect //收縮效果撒璧,如一塊布被抽走(不支持過渡方向)
- **rippleEffect **//滴水效果(不支持過渡方向)
- **pageCurl ** //向上翻頁效果
- pageUnCurl //向下翻頁效果
- **cameraIrisHollowOpen ** //相機(jī)鏡頭打開效果(不支持過渡方向)
- cameraIrisHollowClose //相機(jī)鏡頭關(guān)上效果(不支持過渡方向)
下面看下suckEffect效果:
9.2 subtype動畫過渡方向
規(guī)定了動畫從哪個方面過來
- ** kCATransitionFromRightl**
- ** kCATransitionFromLeftl**
- ** kCATransitionFromTopl**
- ** kCATransitionFromBottoml**
9.2 startProgress和endProgress動畫起點(diǎn)/終點(diǎn)百分比
transition.startProgress = 0.5;
效果:
由此可以看出:動畫初始時刻已經(jīng)執(zhí)行了0.5,所以我們看到的是執(zhí)行剩余部分的0.5部分笨使。
transition.endProgress = 0.8;
效果:
由此可以看出:動畫在執(zhí)行到0.8進(jìn)度的時候卿樱,突然結(jié)束
10. CASpringAnimation彈簧動畫
@interface CASpringAnimation : CABasicAnimation
@property CGFloat mass;//目標(biāo)質(zhì)量
@property CGFloat stiffness;//勁度系數(shù)
@property CGFloat damping;//阻尼系數(shù)
@property CGFloat initialVelocity;//初始速度
@property(readonly) CFTimeInterval settlingDuration;//結(jié)算時間,結(jié)算時間 返回彈簧動畫到停止時的估算時間硫椰,根據(jù)當(dāng)前的動畫參數(shù)估算
通常彈簧動畫的時間使用結(jié)算時間比較準(zhǔn)確
@end
代碼示例:
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic,strong) CALayer *testLayer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
CALayer *testLayer = [CALayer new];
self.testLayer = testLayer;
[self.view.layer addSublayer:testLayer];
testLayer.backgroundColor = [UIColor redColor].CGColor;
testLayer.frame = CGRectMake(150, 100, 100, 100);
UIView *lineView1 = [[UIView alloc ] initWithFrame:CGRectMake(0, self.testLayer.position.y+200.0, [UIScreen mainScreen].bounds.size.width, 1)];
[self.view addSubview:lineView1];
lineView1.backgroundColor = [UIColor blueColor];
UIView *lineView2 = [[UIView alloc ] initWithFrame:CGRectMake(0, self.testLayer.position.y, [UIScreen mainScreen].bounds.size.width, 1)];
[self.view addSubview:lineView2];
lineView2.backgroundColor = [UIColor blackColor];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
CASpringAnimation *spring =[CASpringAnimation animation];
spring.keyPath = @"position.y";
spring.fromValue = @(self.testLayer.position.y);
spring.toValue = @(self.testLayer.position.y+200.0);
spring.mass = 5;//質(zhì)量
spring.damping = 30;//阻尼系數(shù)
spring.stiffness = 300;//勁度系數(shù)
spring.initialVelocity = 0;//初始化速度
spring.duration = spring.settlingDuration;//動畫執(zhí)行時間
NSLog(@"settlingDuration=%lf",spring.settlingDuration);
[self.testLayer addAnimation:spring forKey:nil];
}
@end
運(yùn)行效果: