動畫的繼承結(jié)構(gòu)
CAAnimation{CAPropertyAnimation{CABasicAnimation{CASpringAnimation}CAKeyframeAnimation}CATransitionCAAnimationGroup}
CAAnimation(動畫根類,不可以直接使用)
CAAnimation-屬性(復(fù)雜點的屬性炼蹦,下面會有詳細(xì)解釋)
//動畫的代理回調(diào),下面會有@property(nullable,strong)iddelegate;//動畫執(zhí)行完以后是否移除動畫,默認(rèn)YES@property(getter=isRemovedOnCompletion)BOOLremovedOnCompletion;//動畫的動作規(guī)則,包含以下值//kCAMediaTimingFunctionLinear 勻速//kCAMediaTimingFunctionEaseIn 慢進(jìn)快出//kCAMediaTimingFunctionEaseOut 快進(jìn)慢出//kCAMediaTimingFunctionEaseInEaseOut 慢進(jìn)慢出 中間加速//kCAMediaTimingFunctionDefault 默認(rèn)@property(nullable,strong)CAMediaTimingFunction*timingFunction;
以上屬性的詳解:
委托:動畫執(zhí)行的代理,在動畫開始前設(shè)定,不用顯式的寫在代碼里,它包含兩個方法:
動畫開始回調(diào)
- (void)animationDidStart:(CAAnimation *)anim;
動畫結(jié)束回調(diào)
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
removedOnCompletion:動畫完成后是否移除動畫默認(rèn)為YES此屬性為YES時歪架,在fillMode不可用,具體為什么不可用档礁,可以自己結(jié)合兩個屬性分析一下,這里不再贅述赚抡。
timingFunction設(shè)置動畫速度曲線爬坑,默認(rèn)值上面已經(jīng)給出下面說它的幾個方法:
。這兩個方法是一樣的如果我們對系統(tǒng)自帶的速度函數(shù)不滿意涂臣,可以通過這兩個函數(shù)創(chuàng)建一個自己喜歡的速度曲線函數(shù)盾计,具體用法可以參考這篇文章CAMediaTimingFunction使用的
+ (instancetype)functionWithControlPoints:(float)c1x :(float)c1y :(float)c2x :(float)c2y;
- (instancetype)initWithControlPoints:(float)c1x :(float)c1y :(float)c2x :(float)c2y;
電子雜志曲線的函數(shù)的緩沖點售担,具體用法可以參考這篇文章:iOS-核心動畫高級編程/ 10-緩沖
- (void)getControlPointAtIndex:(size_t)idx values:(float[2])ptr;
CAAnimation 協(xié)議的屬性
//開始時間.這個屬性比較復(fù)雜,傻瓜用法為:CACurrentMediaTime() + x,//其中x為延遲時間.如果設(shè)置 beginTime = CACurrentMediaTime() + 1.0,產(chǎn)生的效果為延遲一秒執(zhí)行動畫,下面詳解原理@propertyCFTimeIntervalbeginTime;//動畫執(zhí)行時間,此屬性和speed有關(guān)系speed默認(rèn)為1.0,如果speed設(shè)置為2.0,那么動畫執(zhí)行時間則為duration*(1.0/2.0).@propertyCFTimeIntervalduration;//動畫執(zhí)行速度,它duration的關(guān)系參考上面解釋@propertyfloatspeed;//動畫的時間延遲,這個屬性比較復(fù)雜,下面詳解@propertyCFTimeIntervaltimeOffset;//重復(fù)執(zhí)行次數(shù)@propertyfloatrepeatCount;//重復(fù)執(zhí)行時間,此屬性優(yōu)先級大于repeatCount.也就是說如果repeatDuration設(shè)置為1秒重復(fù)10次,那么它會在1秒內(nèi)執(zhí)行完動畫.@propertyCFTimeIntervalrepeatDuration;//是否自動翻轉(zhuǎn)動畫,默認(rèn)NO.如果設(shè)置YES,那么整個動畫的執(zhí)行效果為A->B->A.@propertyBOOLautoreverses;//動畫的填充方式,默認(rèn)為: kCAFillModeRemoved,包含以下值//kCAFillModeForwards//動畫結(jié)束后回到準(zhǔn)備狀態(tài)//kCAFillModeBackwards//動畫結(jié)束后保持最后狀態(tài)//kCAFillModeBoth//動畫結(jié)束后回到準(zhǔn)備狀態(tài),并保持最后狀態(tài)//kCAFillModeRemoved//執(zhí)行完成移除動畫@property(copy)NSString*fillMode;
以上屬性的詳解:
BEGINTIME:剛才上面簡單解釋了下這個屬性的用法:CACurrentMediaTime()+ x。會使動畫延遲執(zhí)行點ˉx秒不知道到這里有沒有人想過如果-x署辉?會出現(xiàn)怎么樣效果假設(shè)我們有執(zhí)行一個3秒的動畫族铆,設(shè)置然后beginTime = CACurrentMediaTime()- 1.5那么執(zhí)行動畫你會發(fā)現(xiàn)動畫只會執(zhí)行后半段,就是也哭尝。只執(zhí)行后面的3-1.5s的動畫哥攘。為什么會這樣?其實動畫都有一個時間表(時間線)的概念材鹦。動畫開始執(zhí)行都是基于這個時間線的絕對時間逝淹,這個時間和它的父類有關(guān)(系統(tǒng)的屬性注釋可以看到)。默認(rèn)的CALayer的的BEGINTIME為零桶唐,如果這個值為零的話栅葡,系統(tǒng)會把它設(shè)置為CACurrentMediaTime(),那么這個時間就是正常執(zhí)行動畫的時間:立即執(zhí)行所以如果設(shè)置你beginTime=CACurrentMediaTime()+x;它會把它的執(zhí)行時間線推遲x秒尤泽,就是也欣簇。晚執(zhí)行x秒,如果你beginTime=CACurrentMediaTime()-x;那它開始的時候會從你動畫對應(yīng)的絕對時間開始執(zhí)行坯约。
timeOffset:時間偏移量熊咽,默認(rèn)為0;既然它是時間偏移量,那么它即和動畫時間相關(guān)這么解釋:假設(shè)我們設(shè)置一個動畫時間為5秒鬼店,動畫執(zhí)行的過程為1->2->3->4->5网棍,這時候如果你設(shè)置timeOffset = 2s它那么的執(zhí)行過程就會變成3->4->5->1->2如果你設(shè)置timeOffset = 4s那么它的執(zhí)行過程就會變成5->1->2->3->4,這么說應(yīng)該很明白了吧妇智?
CAPropertyAnimation屬性動畫滥玷,抽象類,不能直接使用
CAPropertyAnimation的屬性
//需要動畫的屬性值@property(nullable,copy)NSString*keyPath;//屬性動畫是否以當(dāng)前動畫效果為基礎(chǔ),默認(rèn)為NO@property(getter=isAdditive)BOOLadditive;//指定動畫是否為累加效果,默認(rèn)為NO@property(getter=isCumulative)BOOLcumulative;//此屬性相當(dāng)于CALayer中的transform屬性,下面會詳解@property(nullable,strong)CAValueFunction*valueFunction;
以上屬性的詳解:
CAPropertyAnimation是屬性動畫顧名思義也就是針對屬性才可以做的動畫那它可以對誰的屬性可以做動畫是的CALayer的屬性巍棱,比如:惑畴?界限,位置等那么問題來了航徙,我們改變的CALayer的位置可以如贷。設(shè)置直接[CAPropertyAnimation animationWithKeyPath:@"position"]如果我們設(shè)置它的變換(CATransform3D)呢?CATransform3D是一個矩陣到踏,如果我們想為它做動畫怎么辦杠袱?下面這個屬性就是用來解決這個問題的。
valueFunction:我們來看它可以設(shè)置的值:
kCAValueFunctionRotateX
kCAValueFunctionRotateY
kCAValueFunctionRotateZ
kCAValueFunctionScale
kCAValueFunctionScaleX
kCAValueFunctionScaleY
kCAValueFunctionScaleZ
kCAValueFunctionTranslate
kCAValueFunctionTranslateX
kCAValueFunctionTranslateY
kCAValueFunctionTranslateZ
說到這里大家應(yīng)該都知道該怎么用了吧?窝稿。
CAPropertyAnimation的方法
//通過key創(chuàng)建一個CAPropertyAnimation對象+ (instancetype)animationWithKeyPath:(nullableNSString*)path;
下面我們來看一下可以設(shè)置屬性動畫的屬性歸總:
CATransform3D{
rotation旋轉(zhuǎn)
transform.rotation.x
transform.rotation.y
transform.rotation.z
scale縮放
transform.scale.x
transform.scale.y
transform.scale.z
translation平移
transform.translation.x
transform.translation.y
transform.translation.z
}CGPoint{
position
position.x
position.y
}CGRect{
bounds
bounds.size
bounds.size.width
bounds.size.height
bounds.origin
bounds.origin.x
bounds.origin.y
}property{
opacity
backgroundColor
cornerRadius
borderWidth
contents
Shadow{
shadowColor
shadowOffset
shadowOpacity
shadowRadius
}}
總結(jié):CAAnimation是基類楣富,CAPropertyAnimation是抽象類,兩者都不可以直接使用伴榔,那我們只有使用它的子類了纹蝴。
CABasicAnimation基本動畫
CABasicAnimation的屬性
//開始值@property(nullable,strong)idfromValue;//結(jié)束值@property(nullable,strong)idtoValue;//結(jié)束值@property(nullable,strong)idbyValue;
這三個屬性之間的規(guī)則
fromValue狀語從句:toValue不為空庄萎,的動畫會效果從fromValue的值變化到toValue。
fromValue狀語從句:byValue都不為空塘安,的動畫效果將會從fromValue變化到fromValue+byValue
toValue狀語從句:byValue都不為空糠涛,的動畫效果將會從toValue-byValue變化到toValue
只有fromValue的值不為空,的動畫效果將會從fromValue的值變化到當(dāng)前的狀態(tài)兼犯。
只有toValue的值不為空忍捡,的動畫效果將會從當(dāng)前狀態(tài)的值變化到toValue的值。
只有byValue的值不為空免都,動畫的效果將會從當(dāng)前的值變化到(當(dāng)前狀態(tài)的值+byValue)的值锉罐。
CABasicAnimation看起來不太復(fù)雜,但實際只用這個就足以可以做很多種動畫了绕娘,下面簡單用一下脓规,先看效果:
CABasicAnimation.gif
然后再看下實現(xiàn)代碼:
#import"ViewController.h"#import"TFEasyCoder.h"@interfaceViewController()@property(nonatomic,strong)UIView*demoView;@end@implementationViewController- (void)viewDidLoad {? ? [superviewDidLoad];? ? kdeclare_weakself;NSArray*titles = @[@"淡入淡出",@"縮放",@"旋轉(zhuǎn)",@"平移"];for(unsignedinti =0; i < titles.count; i++) {? ? ? ? [UIButtoneasyCoder:^(UIButton*ins) {? ? ? ? ? ? [weakSelf.viewaddSubview:ins];? ? ? ? ? ? ins.backgroundColor= [UIColorbrownColor];? ? ? ? ? ? ins.tag= i;? ? ? ? ? ? ins.frame=CGRectMake(10,50+80* i,100,60);? ? ? ? ? ? [ins setTitle:titles[i] forState:UIControlStateNormal];? ? ? ? ? ? [ins addTarget:selfaction:@selector(animationBegin:) forControlEvents:UIControlEventTouchUpInside];? ? ? ? }];? ? }? ? [UIVieweasyCoder:^(UIView*ins) {? ? ? ? ins.frame=CGRectMake(0,0,100,100);? ? ? ? ins.backgroundColor= [UIColorredColor];? ? ? ? ins.center=self.view.center;? ? ? ? weakSelf.demoView= ins;? ? ? ? [weakSelf.viewaddSubview:weakSelf.demoView];? ? }];}-(void)animationBegin:(UIButton*)btn{CABasicAnimation*animation =nil;switch(btn.tag) {case0:{//淡如淡出animation = [CABasicAnimationanimationWithKeyPath:@"opacity"];? ? ? ? ? ? [animation setFromValue:@1.0];? ? ? ? ? ? [animation setToValue:@0.1];? ? ? ? }break;case1:{//縮放animation = [CABasicAnimationanimationWithKeyPath:@"transform.scale"];? ? ? ? ? ? [animation setFromValue:@1.0];//設(shè)置起始值[animation setToValue:@0.1];//設(shè)置目標(biāo)值}break;case2:{//旋轉(zhuǎn)animation = [CABasicAnimationanimationWithKeyPath:@"transform.rotation"];//setFromValue不設(shè)置,默認(rèn)以當(dāng)前狀態(tài)為準(zhǔn)[animation setToValue:@(M_PI)];? ? ? ? }break;case3:{//平移animation = [CABasicAnimationanimationWithKeyPath:@"position"];//setFromValue不設(shè)置,默認(rèn)以當(dāng)前狀態(tài)為準(zhǔn)[animation setToValue:[NSValuevalueWithCGPoint:CGPointMake(self.view.center.x,self.view.center.y+200)]];? ? ? ? }break;default:break;? ? }? ? [animation setDelegate:self];//代理回調(diào)[animation setDuration:0.25];//設(shè)置動畫時間,單次動畫時間[animation setRemovedOnCompletion:NO];//默認(rèn)為YES,設(shè)置為NO時setFillMode有效/**
*設(shè)置時間函數(shù)CAMediaTimingFunction
*kCAMediaTimingFunctionLinear 勻速
*kCAMediaTimingFunctionEaseIn 開始速度慢险领,后來速度快
*kCAMediaTimingFunctionEaseOut 開始速度快 后來速度慢
*kCAMediaTimingFunctionEaseInEaseOut = kCAMediaTimingFunctionDefault 中間速度快侨舆,兩頭速度慢
*/[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseInEaseOut]];//設(shè)置自動翻轉(zhuǎn)//設(shè)置自動翻轉(zhuǎn)以后單次動畫時間不變,總動畫時間增加一倍绢陌,它會讓你前半部分的動畫以相反的方式動畫過來//比如說你設(shè)置執(zhí)行一次動畫挨下,從a到b時間為1秒,設(shè)置自動翻轉(zhuǎn)以后動畫的執(zhí)行方式為脐湾,先從a到b執(zhí)行一秒臭笆,然后從b到a再執(zhí)行一下動畫結(jié)束[animation setAutoreverses:YES];//kCAFillModeForwards//動畫結(jié)束后回到準(zhǔn)備狀態(tài)//kCAFillModeBackwards//動畫結(jié)束后保持最后狀態(tài)//kCAFillModeBoth//動畫結(jié)束后回到準(zhǔn)備狀態(tài),并保持最后狀態(tài)//kCAFillModeRemoved//執(zhí)行完成移除動畫[animation setFillMode:kCAFillModeBoth];//將動畫添加到layer,添加到圖層開始執(zhí)行動畫,//注意:key值的設(shè)置與否會影響動畫的效果//如果不設(shè)置key值每次執(zhí)行都會創(chuàng)建一個動畫秤掌,然后創(chuàng)建的動畫會疊加在圖層上//如果設(shè)置key值愁铺,系統(tǒng)執(zhí)行這個動畫時會先檢查這個動畫有沒有被創(chuàng)建,如果沒有的話就創(chuàng)建一個闻鉴,如果有的話就重新從頭開始執(zhí)行這個動畫//你可以通過key值獲取或者刪除一個動畫://[self.demoView.layer animationForKey:@""];//[self.demoView.layer removeAnimationForKey:@""][self.demoView.layeraddAnimation:animation forKey:@"baseanimation"];}/**
*? 動畫開始和動畫結(jié)束時 self.demoView.center 是一直不變的茵乱,說明動畫并沒有改變視圖本身的位置
*/- (void)animationDidStart:(CAAnimation*)anim{NSLog(@"動畫開始------:%@",NSStringFromCGPoint(self.demoView.center));}- (void)animationDidStop:(CAAnimation*)anim finished:(BOOL)flag{NSLog(@"動畫結(jié)束------:%@",NSStringFromCGPoint(self.demoView.center));}
以上效果和代碼還有注釋都解釋的很詳細(xì)了,然后源碼在這里:人口統(tǒng)計學(xué)基本動畫
CASpringAnimation彈性動畫
CASpringAnimation的屬性(iOS9新加)
//理解下面的屬性的時候可以結(jié)合現(xiàn)實物理現(xiàn)象,比如把它想象成一個彈簧上掛著一個金屬小球//質(zhì)量,振幅和質(zhì)量成反比@propertyCGFloatmass;//剛度系數(shù)(勁度系數(shù)/彈性系數(shù)),剛度系數(shù)越大,形變產(chǎn)生的力就越大,運動越快@propertyCGFloatstiffness;//阻尼系數(shù),阻止彈簧伸縮的系數(shù),阻尼系數(shù)越大,停止越快,可以認(rèn)為它是阻力系數(shù)@propertyCGFloatdamping;//初始速率,動畫視圖的初始速度大小速率為正數(shù)時,速度方向與運動方向一致,速率為負(fù)數(shù)時,速度方向與運動方向相反.@propertyCGFloatinitialVelocity;//結(jié)算時間,只讀.返回彈簧動畫到停止時的估算時間孟岛,根據(jù)當(dāng)前的動畫參數(shù)估算通常彈簧動畫的時間使用結(jié)算時間比較準(zhǔn)確@property(readonly)CFTimeIntervalsettlingDuration;
下面我們寫一個演示看看效果:
彈簧彈性動畫.gif注意
以上GIF的代碼為:
CASpringAnimation*spring = [CASpringAnimationanimationWithKeyPath:@"position.y"];spring.damping=5;spring.stiffness=100;spring.mass=1;spring.initialVelocity=0;spring.duration= spring.settlingDuration;spring.fromValue= @(self.demoView1.center.y);spring.toValue= @(self.demoView1.center.y+ (btn.selected?+200:-200));spring.fillMode= kCAFillModeForwards;[self.demoView1.layeraddAnimation:spring forKey:nil];
CASpringAnimation效果不錯瓶竭,但是很不幸只有iOS9 +系統(tǒng)才能使用,這就很操蛋了以前項目有過這樣的需求渠羞,然后就自己寫了一個類似的動畫斤贰,效果在下面:
自定義彈性動畫.gif注意
然后上面自定義彈性動畫的代碼在這里:
#import"UIView+ShakeAnimation.h"#importtypedefvoid(^RunAnimationBlock)();@interfaceUIView()@property(nonatomic,copy)RunAnimationBlock block;@end@implementationUIView(ShakeAnimation)-(void)startAnimationFromFrame:(CGRect)framef? ? ? ? ? ? ? ? ? ? ? toFrame:(CGRect)framet? ? ? ? ? ? ? ? ? ? ? duration:(CGFloat)duration? ? ? ? ? ? ? ? ? ? shakeTimes:(NSInteger)times? ? ? ? ? ? ? ? stretchPercent:(CGFloat)stretchPercent? ? ? ? ? ? ? ? ? ? completion:(void(^)(BOOLfinished))completion{self.layer.masksToBounds=YES;? ? __blockCGFloatperTime = duration / times;? ? __blockCGFloatperx = (framet.origin.x- framef.origin.x) * stretchPercent / times;? ? __blockCGFloatpery = (framet.origin.y- framef.origin.y) * stretchPercent / times;? ? __blockCGFloatperw = (framet.size.width- framef.size.width) * stretchPercent / times;? ? __blockCGFloatperh = (framet.size.height- framef.size.height) * stretchPercent / times;? ? __blockUIView* tmpView =self;? ? __blockNSIntegertmpTimes = (NSInteger)times;? ? __blockNSIntegertmpsymbol = -1;? ? __weaktypeof(self) weakSelf =self;self.block= ^{? ? ? ? [UIViewanimateWithDuration:perTime animations:^{CGFloatx = framet.origin.x+ perx * tmpTimes;CGFloaty = framet.origin.y+ pery * tmpTimes;CGFloatw = framet.size.width+ perw * tmpTimes;CGFloath = framet.size.height+ perh * tmpTimes;CGRectrect =CGRectMake(x, y, w, h);? ? ? ? ? ? tmpView.frame= rect;? ? ? ? }completion:^(BOOLfinished) {? ? ? ? ? ? tmpTimes = tmpTimes + tmpsymbol;? ? ? ? ? ? tmpTimes = - tmpTimes;? ? ? ? ? ? tmpsymbol = - tmpsymbol;if(tmpTimes !=0) {? ? ? ? ? ? ? ? weakSelf.block();? ? ? ? ? ? }else{? ? ? ? ? ? ? ? [UIViewanimateWithDuration:perTime animations:^{? ? ? ? ? ? ? ? ? ? tmpView.frame= framet;? ? ? ? ? ? ? ? }completion:^(BOOLfinished) {? ? ? ? ? ? ? ? ? ? completion(YES);? ? ? ? ? ? ? ? }];? ? ? ? ? ? }? ? ? ? }];? ? };self.block();}staticcharRunAnimationBlockKey;-(RunAnimationBlock)block{returnobjc_getAssociatedObject(self, &RunAnimationBlockKey);}-(void)setBlock:(RunAnimationBlock)block{? ? objc_setAssociatedObject(self, &RunAnimationBlockKey, block, OBJC_ASSOCIATION_COPY_NONATOMIC);}@end
調(diào)用:
[self.demoView2 startAnimationFromFrame:CGRectMake(10,300,100,100)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? toFrame:CGRectMake(10,300,300,100)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? duration:0.5shakeTimes:5stretchPercent:0.3completion:^(BOOL finished) {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? NSLog(@"======over======:%@",self.demoView1);? ? ? ? ? ? ? ? ? ? ? ? ? ? }];
上面兩個彈性動畫的代碼在這里:人口統(tǒng)計學(xué)彈性動畫
CAKeyframeAnimation關(guān)鍵幀動畫
CAKeyframeAnimation的屬性
//關(guān)鍵幀值數(shù)組,一組變化值@property(nullable,copy)NSArray*values;//關(guān)鍵幀幀路徑,優(yōu)先級比values大@property(nullable)CGPathRefpath;//每一幀對應(yīng)的時間,時間可以控制速度.它和每一個幀相對應(yīng),取值為0.0-1.0,不設(shè)則每一幀時間相等.@property(nullable,copy)NSArray *keyTimes;//每一幀對應(yīng)的時間曲線函數(shù),也就是每一幀的運動節(jié)奏@property(nullable,copy)NSArray *timingFunctions;//動畫的計算模式,默認(rèn)值: kCAAnimationLinear.有以下幾個值://kCAAnimationLinear//關(guān)鍵幀為座標(biāo)點的時候,關(guān)鍵幀之間直接直線相連進(jìn)行插值計算;//kCAAnimationDiscrete//離散的,也就是沒有補間動畫//kCAAnimationPaced//平均,keyTimes跟timeFunctions失效//kCAAnimationCubic對關(guān)鍵幀為座標(biāo)點的關(guān)鍵幀進(jìn)行圓滑曲線相連后插值計算,對于曲線的形狀還可以通過tensionValues,continuityValues,biasValues來進(jìn)行調(diào)整自定義,keyTimes跟timeFunctions失效//kCAAnimationCubicPaced在kCAAnimationCubic的基礎(chǔ)上使得動畫運行變得均勻,就是系統(tǒng)時間內(nèi)運動的距離相同,,keyTimes跟timeFunctions失效@property(copy)NSString*calculationMode;//動畫的張力,當(dāng)動畫為立方計算模式的時候此屬性提供了控制插值,因為每個關(guān)鍵幀都可能有張力所以連續(xù)性會有所偏差它的范圍為[-1,1].同樣是此作用@property(nullable,copy)NSArray *tensionValues;//動畫的連續(xù)性值@property(nullable,copy)NSArray *continuityValues;//動畫的偏斜率@property(nullable,copy)NSArray *biasValues;//動畫沿路徑旋轉(zhuǎn)方式,默認(rèn)為nil.它有兩個值://kCAAnimationRotateAuto//自動旋轉(zhuǎn),//kCAAnimationRotateAutoReverse//自動翻轉(zhuǎn)@property(nullable,copy)NSString*rotationMode;
CAKeyframeAnimation可以做很豐富的效果次询,下面展示了幾種純CAKeyframeAnimation做的效果:
CAKeyframeAnimation.gif
以上效果的代碼都比較簡單腋舌,量也比較大,這里就不貼出來了渗蟹,這里可以下載:人口統(tǒng)計學(xué)關(guān)鍵幀動畫
CAAnimationGroup動畫組
CAAnimationGroup的屬性
//只有一個屬性,數(shù)組中接受CAAnimation元素@property(nullable,copy)NSArray *animations;
可以看到CAAnimationGroup只有一個屬性一個CAAnimation數(shù)組块饺。而且它繼承于CAAnimation,它具有CAAnimation的特性雌芽,所以它的用法和CAAnimation是一樣的授艰,不同的是他可以包含?個動畫,也就是說他可以接受很多個CAAnimation并且可以讓它們一起開始世落,這就造成了動畫效果的疊加淮腾,效果就是?個動畫同時進(jìn)行。
來看一個簡單的效果:
CAAnimationGroup.gif
這個是動畫是屉佳,旋轉(zhuǎn)谷朝,抖動,透明度一起作用在一起的效果武花,代碼在這里人口統(tǒng)計學(xué)動畫組
CATransition轉(zhuǎn)場動畫
//轉(zhuǎn)場類型,字符串類型參數(shù).系統(tǒng)提供了四中動畫形式://kCATransitionFade//逐漸消失//kCATransitionMoveIn//移進(jìn)來//kCATransitionPush//推進(jìn)來//kCATransitionReveal//揭開//另外,除了系統(tǒng)給的這幾種動畫效果,我們還可以使用系統(tǒng)私有的動畫效果://@"cube",//立方體翻轉(zhuǎn)效果//@"oglFlip",//翻轉(zhuǎn)效果//@"suckEffect",//收縮效果,動畫方向不可控//@"rippleEffect",//水滴波紋效果,動畫方向不可控//@"pageCurl",//向上翻頁效果//@"pageUnCurl",//向下翻頁效果//@"cameralIrisHollowOpen",//攝像頭打開效果,動畫方向不可控//@"cameraIrisHollowClose",//攝像頭關(guān)閉效果,動畫方向不可控@property(copy)NSString*type;//轉(zhuǎn)場方向,系統(tǒng)一共提供四個方向://kCATransitionFromRight//從右開始//kCATransitionFromLeft//從左開始//kCATransitionFromTop//從上開始//kCATransitionFromBottom//從下開始@property(nullable,copy)NSString*subtype;//開始進(jìn)度,默認(rèn)0.0.如果設(shè)置0.3,那么動畫將從動畫的0.3的部分開始@propertyfloatstartProgress;//結(jié)束進(jìn)度,默認(rèn)1.0.如果設(shè)置0.6,那么動畫將從動畫的0.6部分以后就會結(jié)束@propertyfloatendProgress;//開始進(jìn)度@property(nullable,strong)idfilter;
CATransition也是繼承CAAnimation圆凰,系統(tǒng)默認(rèn)提供了12種動畫樣式,加上4個動畫方向体箕,除了方向不可控的四種效果外专钉,大概一共提供了36種動畫。
另外系統(tǒng)還給UIView的添加了很多分類方法可以快速完成一些簡單的動畫累铅,如下:
的UIView(UIViewAnimation)
@interfaceUIView(UIViewAnimation)+ (void)beginAnimations:(nullableNSString*)animationID context:(nullablevoid*)context;// additional context info passed to will start/did stop selectors. begin/commit can be nested//提交動畫+ (void)commitAnimations;//設(shè)置代理+ (void)setAnimationDelegate:(nullableid)delegate;//設(shè)置動畫開始方法+ (void)setAnimationWillStartSelector:(nullable SEL)selector;//設(shè)置動畫結(jié)束方法+ (void)setAnimationDidStopSelector:(nullable SEL)selector;//設(shè)置動畫時間:default = 0.2+ (void)setAnimationDuration:(NSTimeInterval)duration;//設(shè)置動畫延遲開始時間:default = 0.0+ (void)setAnimationDelay:(NSTimeInterval)delay;//設(shè)置動畫延遲開始日期:default = now ([NSDate date])+ (void)setAnimationStartDate:(NSDate*)startDate;//設(shè)置動畫運動曲線:default =UIViewAnimationCurveEaseInOut//UIViewAnimationCurveEaseInOut,//慢進(jìn)慢出//UIViewAnimationCurveEaseIn, //慢進(jìn)快出//UIViewAnimationCurveEaseOut,//快進(jìn)慢出//UIViewAnimationCurveLinear//勻速+ (void)setAnimationCurve:(UIViewAnimationCurve)curve;//設(shè)置重復(fù)次數(shù): default = 0.0.? May be fractional+ (void)setAnimationRepeatCount:(float)repeatCount;//設(shè)置是否翻轉(zhuǎn)動畫: default = NO. used if repeat+ (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses;//設(shè)置動畫是否從當(dāng)前狀態(tài)開始:default = NO+ (void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState;//設(shè)置動畫類型+ (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView*)view cache:(BOOL)cache;//設(shè)置動畫是否有效+ (void)setAnimationsEnabled:(BOOL)enabled;//+ (BOOL)areAnimationsEnabled;//+ (void)performWithoutAnimation:(void(^)(void))actionsWithoutAnimation//+ (NSTimeInterval)inheritedAnimationDuration@end
的UIView(UIViewAnimationWithBlocks)
@interfaceUIView(UIViewAnimationWithBlocks)//以下方法都大同小異,就不一一做注釋了+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void(^)(void))animations completion:(void(^ __nullable)(BOOLfinished))completion;+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void(^)(void))animations completion:(void(^ __nullable)(BOOLfinished))completion + (void)animateWithDuration:(NSTimeInterval)duration animations:(void(^)(void))animations;+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void(^)(void))animations completion:(void(^ __nullable)(BOOLfinished))completion+ (void)transitionWithView:(UIView*)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void(^ __nullable)(void))animations completion:(void(^ __nullable)(BOOLfinished))completion;+ (void)transitionFromView:(UIView*)fromView toView:(UIView*)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void(^ __nullable)(BOOLfinished))completion;+ (void)performSystemAnimation:(UISystemAnimation)animation onViews:(NSArray<__kindofUIView*> *)views options:(UIViewAnimationOptions)options animations:(void(^ __nullable)(void))parallelAnimations completion:(void(^ __nullable)(BOOLfinished))completionNS_AVAILABLE_IOS(7_0);@end
的UIView(UIViewKeyframeAnimations)
+ (void)animateKeyframesWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewKeyframeAnimationOptions)options animations:(void(^)(void))animations completion:(void(^ __nullable)(BOOLfinished))completion;+ (void)addKeyframeWithRelativeStartTime:(double)frameStartTime relativeDuration:(double)frameDuration animations:(void(^)(void))animations
以上方法比較多跃须,找值得說的簡單說一下吧:
//單視圖轉(zhuǎn)場動畫+ (void)transitionWithView:(UIView*)view? ? ? ? ? ? ? ? ? duration:(NSTimeInterval)duration? ? ? ? ? ? ? ? ? ? options:(UIViewAnimationOptions)options? ? ? ? ? ? ? ? animations:(void(^ __nullable)(void))animations? ? ? ? ? ? ? ? completion:(void(^ __nullable)(BOOLfinished))completion//雙視圖轉(zhuǎn)場動畫+ (void)transitionFromView:(UIView*)fromView? ? ? ? ? ? ? ? ? ? toView:(UIView*)toView? ? ? ? ? ? ? ? ? duration:(NSTimeInterval)duration? ? ? ? ? ? ? ? ? ? options:(UIViewAnimationOptions)options? ? ? ? ? ? ? completion:(void(^ __nullable)(BOOLfinished))completion
這兩個都是轉(zhuǎn)場動畫,不同的是第一個是單視圖轉(zhuǎn)場娃兽,第二個是雙視圖轉(zhuǎn)場不過需要注意的是:單視圖轉(zhuǎn)場動畫只能用作屬性動畫做不到的轉(zhuǎn)場效果菇民,比如屬性動畫不能給的UIImageView的形象賦值操作做動畫效果等。
我們可以看到以上兩個方法中都有一個共同的參數(shù):
UIViewAnimationOptions
typedefNS_OPTIONS(NSUInteger, UIViewAnimationOptions){? ? UIViewAnimationOptionLayoutSubviews? ? ? ? ? ? =1<<0,? ? UIViewAnimationOptionAllowUserInteraction? ? ? =1<<1,// turn on user interaction while animatingUIViewAnimationOptionBeginFromCurrentState? ? =1<<2,// start all views from current value, not initial valueUIViewAnimationOptionRepeat? ? ? ? ? ? ? ? ? ? =1<<3,// repeat animation indefinitelyUIViewAnimationOptionAutoreverse? ? ? ? ? ? ? =1<<4,// if repeat, run animation back and forthUIViewAnimationOptionOverrideInheritedDuration =1<<5,// ignore nested durationUIViewAnimationOptionOverrideInheritedCurve? ? =1<<6,// ignore nested curveUIViewAnimationOptionAllowAnimatedContent? ? ? =1<<7,// animate contents (applies to transitions only)UIViewAnimationOptionShowHideTransitionViews? =1<<8,// flip to/from hidden state instead of adding/removingUIViewAnimationOptionOverrideInheritedOptions? =1<<9,// do not inherit any options or animation typeUIViewAnimationOptionCurveEaseInOut? ? ? ? ? ? =0<<16,// defaultUIViewAnimationOptionCurveEaseIn? ? ? ? ? ? ? =1<<16,? ? UIViewAnimationOptionCurveEaseOut? ? ? ? ? ? ? =2<<16,? ? UIViewAnimationOptionCurveLinear? ? ? ? ? ? ? =3<<16,? ? UIViewAnimationOptionTransitionNone? ? ? ? ? ? =0<<20,// defaultUIViewAnimationOptionTransitionFlipFromLeft? ? =1<<20,? ? UIViewAnimationOptionTransitionFlipFromRight? =2<<20,? ? UIViewAnimationOptionTransitionCurlUp? ? ? ? ? =3<<20,? ? UIViewAnimationOptionTransitionCurlDown? ? ? ? =4<<20,? ? UIViewAnimationOptionTransitionCrossDissolve? =5<<20,? ? UIViewAnimationOptionTransitionFlipFromTop? ? =6<<20,? ? UIViewAnimationOptionTransitionFlipFromBottom? =7<<20,} NS_ENUM_AVAILABLE_IOS(4_0);
可以看到系統(tǒng)給到的是一個位移枚舉投储,這就意味著這個枚舉可以多個值同時使用第练,但是怎么用呢?其實那些枚舉值可以分為三個部分轻要。
我們分別看一下每個枚舉的意思:
第一部分:動畫效果
UIViewAnimationOptionTransitionNone//沒有效果UIViewAnimationOptionTransitionFlipFromLeft//從左水平翻轉(zhuǎn)UIViewAnimationOptionTransitionFlipFromRight//從右水平翻轉(zhuǎn)UIViewAnimationOptionTransitionCurlUp//翻書上掀UIViewAnimationOptionTransitionCurlDown//翻書下蓋UIViewAnimationOptionTransitionCrossDissolve//融合UIViewAnimationOptionTransitionFlipFromTop//從上垂直翻轉(zhuǎn)? ? ? ? ? ? ? ? ? ? UIViewAnimationOptionTransitionFlipFromBottom//從下垂直翻轉(zhuǎn)
第二部分:動畫運動曲線
//開始慢复旬,加速到中間,然后減慢到結(jié)束UIViewAnimationOptionCurveEaseInOut//開始慢冲泥,加速到結(jié)束UIViewAnimationOptionCurveEaseIn//開始快驹碍,減速到結(jié)束UIViewAnimationOptionCurveEaseOut//線性運動UIViewAnimationOptionCurveLinear
第三部分:其他
//默認(rèn),跟父類作為一個整體UIViewAnimationOptionLayoutSubviews//設(shè)置了這個凡恍,主線程可以接收點擊事件UIViewAnimationOptionAllowUserInteraction//從當(dāng)前狀態(tài)開始動畫志秃,父層動畫運動期間,開始子層動畫.UIViewAnimationOptionBeginFromCurrentState//重復(fù)執(zhí)行動畫嚼酝,從開始到結(jié)束浮还, 結(jié)束后直接跳到開始態(tài)UIViewAnimationOptionRepeat//反向執(zhí)行動畫,結(jié)束后會再從結(jié)束態(tài)->開始態(tài)UIViewAnimationOptionAutoreverse//忽略繼承自父層持續(xù)時間闽巩,使用自己持續(xù)時間(如果存在)UIViewAnimationOptionOverrideInheritedDuration//忽略繼承自父層的線性效果钧舌,使用自己的線性效果(如果存在)UIViewAnimationOptionOverrideInheritedCurve//允許同一個view的多個動畫同時進(jìn)行UIViewAnimationOptionAllowAnimatedContent//視圖切換時直接隱藏舊視圖担汤、顯示新視圖,而不是將舊視圖從父視圖移除(僅僅適用于轉(zhuǎn)場動畫)? ? ? ? ? ? UIViewAnimationOptionShowHideTransitionViews//不繼承父動畫設(shè)置或動畫類型.UIViewAnimationOptionOverrideInheritedOptions
這下可以看到洼冻,這些枚舉功能都不一樣但是可以隨意組合崭歧,但是組合的時候需要注意,類型同一枚舉的一起不能使用比如UIViewAnimationOptionCurveEaseIn狀語從句:UIViewAnimationOptionCurveEaseOut
然后我們看一下轉(zhuǎn)場動畫的一些效果:
單視圖轉(zhuǎn)場
單視圖轉(zhuǎn)場.gif注意
雙視圖轉(zhuǎn)場
雙視圖轉(zhuǎn)場.gif注意
CATransition視圖轉(zhuǎn)場
CATransition.gif