iOS的CoreAnimation開(kāi)發(fā)框架中的Layer層動(dòng)畫制作解析
CAAnimation動(dòng)畫體系的介紹
CAAnimation是CoreAnimation框架中執(zhí)行動(dòng)畫對(duì)象的基類,下面有一張圖,是我手畫的,不太美觀,但是可以將與CAAnimation相關(guān)的幾個(gè)動(dòng)畫類的關(guān)系表達(dá)清楚:
從上圖中可以看到,從CAAnimation中繼承出三個(gè)子類,分別是用于創(chuàng)建屬性動(dòng)畫的CAPropertyAnimation,創(chuàng)建轉(zhuǎn)場(chǎng)動(dòng)畫的CATransition和創(chuàng)建組合動(dòng)畫的CAAnimationGroup。
我們就先從根類開(kāi)始探討。
1.CAAnimation屬性和方法
CAAnimation作為動(dòng)畫對(duì)象的基類,其中封裝了動(dòng)畫的基礎(chǔ)屬性,如下:
//通過(guò)類方法創(chuàng)建一個(gè)CAAnimation對(duì)象
+ (instancetype)animation;
//動(dòng)畫執(zhí)行的時(shí)序模式
@property(nullable, strong) CAMediaTimingFunction *timingFunction;
//代理
@property(nullable, strong) id delegate;
//是否動(dòng)畫完成時(shí)將動(dòng)畫對(duì)象移除掉
@property(getter=isRemovedOnCompletion) BOOL removedOnCompletion;
timingFunction定義了動(dòng)畫執(zhí)行的時(shí)序效果,CAMediaTimingFunction的創(chuàng)建方式如下:
/*
CAAnimation的代理方法入如下幾個(gè):
name參數(shù)決定的執(zhí)行的效果,可選參數(shù)如下
//線性執(zhí)行
NSString * const kCAMediaTimingFunctionLinear;
//淡入 在動(dòng)畫開(kāi)始時(shí) 淡入效果
NSString * const kCAMediaTimingFunctionEaseIn;
//淡出 在動(dòng)畫結(jié)束時(shí) 淡出效果
NSString * const kCAMediaTimingFunctionEaseOut;
//淡入淡出
NSString * const kCAMediaTimingFunctionEaseInEaseOut;
//默認(rèn)效果
NSString * const kCAMediaTimingFunctionDefault;
*/
+ (instancetype)functionWithName:(NSString *)name;
//動(dòng)畫開(kāi)始時(shí)執(zhí)行的回調(diào)
2.CAPropertyAnimation屬性與方法
- (void)animationDidStart:(CAAnimation *)anim;
//動(dòng)畫結(jié)束后執(zhí)行的回調(diào)
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
CAPropertyAnimation是繼承于CAAnimation專門用來(lái)創(chuàng)建與屬性相關(guān)的動(dòng)畫的類:
//創(chuàng)建對(duì)象 參數(shù)中的path就是我們要執(zhí)行動(dòng)畫的屬性
上面這些屬性中,只有一個(gè)需要我們注意,valueFunction是專門為了transform動(dòng)畫而設(shè)置的,因?yàn)槲覀儧](méi)有辦法直接改變transform3D中的屬性,通過(guò)這個(gè)參數(shù),可以幫助我們直接操作transfrom3D屬性變化產(chǎn)生動(dòng)畫效果,舉例如下,一個(gè)繞Z軸旋轉(zhuǎn)的動(dòng)畫:
//例如,如果傳入@"backgroundColor" 當(dāng)layer的背景顏色改變時(shí),就會(huì)執(zhí)行我們?cè)O(shè)置的動(dòng)畫
+ (instancetype)animationWithKeyPath:(nullable NSString *)path;
//這個(gè)屬性確定動(dòng)畫執(zhí)行的狀態(tài)是否疊加在控件的原狀態(tài)上
//默認(rèn)設(shè)置為NO,如果我們執(zhí)行兩次位置移動(dòng)的動(dòng)畫,會(huì)從同一位置執(zhí)行兩次
//如果設(shè)置為YES,則會(huì)在第一次執(zhí)行的基礎(chǔ)上執(zhí)行第二次動(dòng)畫
@property(getter=isAdditive) BOOL additive;
//這個(gè)屬性對(duì)重復(fù)執(zhí)行的動(dòng)畫有效果
//默認(rèn)為NO,重復(fù)執(zhí)行的動(dòng)畫每次都是從起始狀態(tài)開(kāi)始
//如果設(shè)置為yes,則為此執(zhí)行都會(huì)在上一次執(zhí)行的基礎(chǔ)上執(zhí)行
@property(getter=isCumulative) BOOL cumulative;
//這個(gè)屬性和transfron屬性的動(dòng)畫執(zhí)行相關(guān)
@property(nullable, strong) CAValueFunction *valueFunction;
//繞z軸旋轉(zhuǎn)的動(dòng)畫
實(shí)際上,使用點(diǎn)的方式也是可以訪問(wèn)到相應(yīng)屬性的,如果不設(shè)置valueFunction,使用如下方法也是可以進(jìn)行繞Z軸旋轉(zhuǎn)的:
CABasicAnimation * ani = [CABasicAnimation animationWithKeyPath:@"transform"];
//從0度開(kāi)始
ani.fromValue = @0;
//旋轉(zhuǎn)到180度
ani.toValue = [NSNumber numberWithFloat:M_PI];
//時(shí)間2S
ani.duration = 2;
//設(shè)置為z軸旋轉(zhuǎn)
ani.valueFunction = [CAValueFunction functionWithName:kCAValueFunctionRotateZ];
//執(zhí)行動(dòng)畫
[layer addAnimation:ani forKey:@""];
//繞z軸旋轉(zhuǎn)的動(dòng)畫
CABasicAnimation * ani = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
//從0度開(kāi)始
ani.fromValue = @0;
//旋轉(zhuǎn)到180度
ani.toValue = [NSNumber numberWithFloat:M_PI];
//時(shí)間2S
ani.duration = 2;
//執(zhí)行動(dòng)畫
[layer addAnimation:ani forKey:@""];
3.CABasicAnimation屬性
CABasicAnimaton是CAPropertyAnimation分出來(lái)的一個(gè)子類,創(chuàng)建基礎(chǔ)的屬性變化動(dòng)畫,例如我們上面的示例代碼,其中屬性如下:
@property(nullable, strong) id fromValue;
上面三個(gè)屬性都是來(lái)確定動(dòng)畫的起始與結(jié)束位置,有如下的含義:
@property(nullable, strong) id toValue;
@property(nullable, strong) id byValue;
(1)fromValue和toValue不為空:動(dòng)畫的值由fromValue變化到toValue
(2)fromValue和byValue不為空:動(dòng)畫的值由fromValue變化到fromValue+byValue
(3)byValue和toValue不為空:動(dòng)畫的值由toValue-byValue變化到toValue
(4)只有fromValue不為空:動(dòng)畫的值由fromValue變化到layer的當(dāng)前狀態(tài)值
(5)只有toValue不為空:動(dòng)畫的值由layer當(dāng)前的值變化到toValue
(6)只有byValue不為空:動(dòng)畫的值由layer當(dāng)前的值變化到layer當(dāng)前的值+byValue
4.CAKeyframeAnimation關(guān)鍵幀動(dòng)畫
CAKeyframeAnimation也是繼承與CAPropertyAnimation的一個(gè)子類,其與CABasicAnimation的不同之處在于雖然其都是改變layer層屬性的動(dòng)畫,但是CABasicAnimation只能設(shè)置初始與結(jié)束狀態(tài),這之間我們沒(méi)辦法控制,而CAKeyframeAnimation可以讓我們?cè)O(shè)置一些關(guān)鍵幀再整個(gè)動(dòng)畫的過(guò)程中。屬性方法如下:
//關(guān)鍵幀的值數(shù)組 例如我們想讓控件沿某個(gè)路徑移動(dòng),這里面存放每個(gè)移動(dòng)的點(diǎn)
示例如下:
@property(nullable, copy) NSArray *values;
//直接設(shè)置路徑,作用域values類似
@property(nullable) CGPathRef path;
//設(shè)置每一幀執(zhí)行的時(shí)間長(zhǎng)短 這個(gè)的取值為0-1,代表占用時(shí)間的比例
@property(nullable, copy) NSArray<NSNumber *> *keyTimes;
//每一幀執(zhí)行過(guò)程中的時(shí)序效果 上面有提過(guò)
@property(nullable, copy) NSArray<CAMediaTimingFunction *> *timingFunctions;
/*
設(shè)置幀的中間值如何計(jì)算
NSString * const kCAAnimationLinear;
NSString * const kCAAnimationDiscrete;
NSString * const kCAAnimationPaced;
NSString * const kCAAnimationCubic;
NSString * const kCAAnimationCubicPaced;
*/
@property(copy) NSString *calculationMode;
CAKeyframeAnimation * ani = [CAKeyframeAnimation animationWithKeyPath:@"position"];
5.CASpringAnimation阻尼動(dòng)畫
ani.values = @[[NSValue valueWithCGPoint:CGPointMake(100, 100)],[NSValue valueWithCGPoint:CGPointMake(120, 100)],[NSValue valueWithCGPoint:CGPointMake(120, 200)],[NSValue valueWithCGPoint:CGPointMake(200, 200)]];
ani.duration = 3;
[layer addAnimation:ani forKey:@""];
通過(guò)CASpringAnimation,可以幫助開(kāi)發(fā)者很輕松的創(chuàng)建出有彈簧效果的動(dòng)畫,主要屬性如下:
//這個(gè)屬性設(shè)置彈簧重物的質(zhì)量 會(huì)影響慣性 必須大于0 默認(rèn)為1
6.CATransition轉(zhuǎn)場(chǎng)動(dòng)畫
@property CGFloat mass;
//設(shè)置彈簧的剛度系數(shù),必須大于0 默認(rèn)為100 這個(gè)越大 則回彈越快
@property CGFloat stiffness;
//阻尼系數(shù) 默認(rèn)為10 必須大于0 這個(gè)值越大 回彈的幅度越小
@property CGFloat damping;
//初始速度
@property CGFloat initialVelocity;
//獲取動(dòng)畫停下來(lái)需要的時(shí)間
@property(readonly) CFTimeInterval settlingDuration;
CATransition和CAPropertyAnimation的不同之處在于當(dāng)layer層出現(xiàn)時(shí),會(huì)產(chǎn)生動(dòng)畫效果,而并不是屬性改變時(shí),屬性如下:
/*
其實(shí),關(guān)于type定義的動(dòng)畫效果,出來(lái)官方定義的,我們還可以使用一些私有的參數(shù),如下:
設(shè)置動(dòng)畫類型
//淡入
NSString * const kCATransitionFade;
//移入
NSString * const kCATransitionMoveIn;
//壓入
NSString * const kCATransitionPush;
//溶解
NSString * const kCATransitionReveal;
*/
@property(copy) NSString *type;
/*
設(shè)置動(dòng)畫的方向
//從右側(cè)進(jìn)
NSString * const kCATransitionFromRight;
//從左側(cè)進(jìn)
NSString * const kCATransitionFromLeft;
//從上側(cè)進(jìn)
NSString * const kCATransitionFromTop;
//從下側(cè)進(jìn)
NSString * const kCATransitionFromBottom;
*/
@property(nullable, copy) NSString *subtype;
(1)pageCurl 翻頁(yè)
(2)rippleEffect 滴水效果
(3)suckEffect 收縮效果,如一塊布被抽走
(4)cube 立方體效果
(5)oglFlip 上下翻轉(zhuǎn)效果
例如:
CATransition * ani = [CATransition animation];
7.CAAnimationGroup動(dòng)畫組
ani.type = @"pageCurl";
ani.subtype = kCATransitionFromRight;
[layer addAnimation:ani forKey:@""];
CAAnimationGroup本身并沒(méi)有定義動(dòng)畫,他可以將我們上面提到的相關(guān)動(dòng)畫進(jìn)行組合:
@property(nullable, copy) NSArray<CAAnimation *> *animations;
高級(jí)動(dòng)畫技巧
1.事務(wù)類
CoreAnimation中還有一個(gè)非常重要的類:CATransaction事物類,這個(gè)可以同時(shí)設(shè)置多個(gè)layer層的動(dòng)畫效果??梢酝ㄟ^(guò)隱式和顯式兩種方式來(lái)進(jìn)行動(dòng)畫操作。
2.CATransaction屬性
對(duì)layer層的屬性操作,都會(huì)形成隱式動(dòng)畫,要使用隱式動(dòng)畫,需要關(guān)閉layer層的animation動(dòng)畫屬性,使用下面的方法:
//關(guān)閉animation動(dòng)畫效果,開(kāi)啟隱式動(dòng)畫
+ (BOOL)disableActions;
+ (void)setDisableActions:(BOOL)flag;
CATransaction用類方式通過(guò)設(shè)置key-value來(lái)進(jìn)行動(dòng)畫的屬性設(shè)置:
+ (nullable id)valueForKey:(NSString *)key;
支持的key值如下:
+ (void)setValue:(nullable id)anObject forKey:(NSString *)key;
//設(shè)置動(dòng)畫持續(xù)時(shí)間
除了隱式的展示動(dòng)畫外,也可以顯式的通過(guò)調(diào)用CATransaction的相關(guān)方法進(jìn)行顯示的提交動(dòng)畫:
NSString * const kCATransactionAnimationDuration;
//設(shè)置停用animation類動(dòng)畫
NSString * const kCATransactionDisableActions;
//設(shè)置動(dòng)畫時(shí)序效果
NSString * const kCATransactionAnimationTimingFunction;
//設(shè)置動(dòng)畫完成后的回調(diào)
NSString * const kCATransactionCompletionBlock;
//動(dòng)畫開(kāi)始
示例如下:
+ (void)begin;
//提交動(dòng)畫
+ (void)commit;
//立即進(jìn)行動(dòng)畫渲染 一般不需調(diào)用
+ (void)flush;
//下面這兩個(gè)方法用于動(dòng)畫事物的加鎖與解鎖 在多線程動(dòng)畫中,保證修改屬性的安全
+ (void)lock;
+ (void)unlock;
[CATransaction begin];
[CATransaction setValue:@1 forKey:kCATransactionAnimationDuration];
layer.backgroundColor = [UIColor blueColor].CGColor;
[CATransaction commit];
相關(guān)文章
iOS利用NSMutableAttributedString實(shí)現(xiàn)富文本的方法小結(jié)
這篇文章主要給大家介紹了關(guān)于iOS利用NSMutableAttributedString如何實(shí)現(xiàn)富文本的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-05-05iOS開(kāi)發(fā)之路--微博“更多”頁(yè)面
本文是IOS開(kāi)發(fā)之路系列文章第五篇,主要講訴了,如何制作微博的更多頁(yè)面,并附上效果圖及源碼,需要的朋友可以參考下,希望能有所幫助2014-08-08Objective-C中利用正則去除非數(shù)字字母漢字方法實(shí)例
正則表達(dá)式對(duì)我們?nèi)粘i_(kāi)發(fā)來(lái)說(shuō)是必不可少的,下面這篇文章主要給大家介紹了關(guān)于Objective-C中如何利用正則去除非數(shù)字字母漢字的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-06-06iOS中UIScrollerView的用法及基于AotoLayout的控件懸停
這篇文章主要介紹了iOS中UIScrollerView的用法及基于AotoLayout的控件懸停,文中對(duì)于UIScrollerView的方法及屬性介紹地非常詳細(xì),十分推薦,示例代碼為Objective-C,需要的朋友可以參考下2016-03-03iOS統(tǒng)計(jì)代碼總行數(shù)的命令(便捷且簡(jiǎn)單)
在工作中有時(shí)候會(huì)需要統(tǒng)計(jì)我們工程的總代碼行數(shù),下面小編給大家分享一個(gè)超便捷超簡(jiǎn)單的方法,通過(guò)一行命令統(tǒng)計(jì)ios代碼總行數(shù),需要的朋友參考下吧2017-11-11IOS 開(kāi)發(fā)之 NSMutableArray與NSArray 的區(qū)別
這篇文章主要介紹了IOS 開(kāi)發(fā)之 NSMutableArray與NSArray 的區(qū)別的相關(guān)資料,希望通過(guò)本文能掌握這部分內(nèi)容,需要的朋友可以參考下2017-09-09IOS 通訊錄的訪問(wèn)和修改的實(shí)現(xiàn)
這篇文章主要介紹了IOS 通訊錄的訪問(wèn)和修改的實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下2017-06-06Dispatch Source Timer的使用及注意事項(xiàng)介紹
這篇文章主要給大家介紹了關(guān)于Dispatch Source Timer使用和一些注意事項(xiàng)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)下吧。2017-09-09