CALayer 和 Core Animation

CALayer

一攒读、簡(jiǎn)介

1.CALayer

簡(jiǎn)單的說(shuō)是層(圖層)的概念绸贡,類似與PS中的圖層。一個(gè)用來(lái)完成繪制凛辣、渲染抱既、動(dòng)畫(huà)等效果的可見(jiàn)的容器。

2.CALayer 與 UIView 的聯(lián)系與區(qū)別

UIView中有一個(gè)layer屬性扁誓,為根圖層防泵。UIView之所以能顯示在屏幕上,完全是因?yàn)樗鼉?nèi)部的CALayer對(duì)象蝗敢。在創(chuàng)建UIView對(duì)象時(shí)捷泞,UIView內(nèi)部會(huì)自動(dòng)創(chuàng)建一個(gè)層(即CALayer對(duì)象),通過(guò)UIView的layer屬性可以訪問(wèn)這個(gè)層寿谴。當(dāng)UIView需要顯示到屏幕上時(shí)锁右,會(huì)調(diào)用drawRect:方法進(jìn)行繪圖,并且會(huì)將所有內(nèi)容繪制在自己的層上,繪圖完畢后咏瑟,系統(tǒng)會(huì)將層拷貝到屏幕上拂到,于是就完成了UIView的顯示。UIView本身不具備顯示的功能码泞,顯示的是UIView的CALayer谆焊。
UIView可以通過(guò)subviews屬性訪問(wèn)所有的子視圖,同樣地浦夷,CALayer也可以通過(guò)sublayers屬性訪問(wèn)所有的子層;UIView可以通過(guò)superview屬性訪問(wèn)父視圖辜王,同樣地劈狐,CALayer也可以通過(guò)superlayer屬性訪問(wèn)父層。
UIView可以通過(guò)addSubview:方法添加子視圖呐馆,同樣地肥缔,CALayer可以通過(guò)addSublayer:方法添加子層。

在使用時(shí)汹来,往往CALayer和UIView都能實(shí)現(xiàn)相同的顯示效果续膳,但是UIView具有交互的能力,可以處理事件收班。如果顯示出來(lái)的東西需要跟用戶進(jìn)行交互的話坟岔,那么就要使用用UIView。

3.常用屬性

屬性 說(shuō)明 是否支持隱式動(dòng)畫(huà)
anchorPoint 和中心點(diǎn)position重合的一個(gè)點(diǎn)摔桦,稱為“錨點(diǎn)”社付,錨點(diǎn)的描述是相對(duì)于x、y位置比例而言的默認(rèn)在圖像中心點(diǎn)(0.5,0.5)的位置
backgroundColor 圖層背景顏色
borderColor 邊框顏色
borderWidth 邊框?qū)挾?/td>
bounds 圖層大小
contents 圖層顯示的內(nèi)容
contentsRect 圖層顯示內(nèi)容的大小和位置
cornerRadius 圓角半徑
doubleSided 圖層背面是否顯示邻耕,默認(rèn)為YES
frame 圖層大小和位置
hidden 是否隱藏
mask 圖層蒙版
maskToBounds 子圖層是否剪切圖層邊界鸥咖,默認(rèn)為NO
opacity 透明度
position 圖層中心點(diǎn)位置
shadowColor 陰影顏色
shadowOffset 陰影偏移量
shadowOpacity 陰影透明度,默認(rèn)為0兄世,設(shè)置陰影必須設(shè)置此屬性
shadowPath 陰影的形狀
shadowRadius 陰影模糊半徑
sublayers 子圖層
sublayerTransform 子圖層形變
transform 圖層形變

注:

  • 在CALayer中很少使用frame屬性啼辣,因?yàn)閒rame本身不支持隱式動(dòng)畫(huà),通常使用bounds和position代替
  • anchorPoint屬性是圖層的錨點(diǎn)御滩,范圍在(01,01)表示在x鸥拧、y軸的比例,這個(gè)點(diǎn)決定著CALayer身上的哪個(gè)點(diǎn)會(huì)與position所指定的位置重合削解,當(dāng)圖層中心點(diǎn)固定后住涉,調(diào)整anchorPoint即可達(dá)到調(diào)整圖層顯示位置的作用(因?yàn)樗肋h(yuǎn)和position重合)

4.隱式動(dòng)畫(huà)屬性

每一個(gè)UIView內(nèi)部都默認(rèn)關(guān)聯(lián)著一個(gè)CALayer,這個(gè)CALayer為Root Layer(根層)钠绍。對(duì)于所有的非Root Layer舆声,即手動(dòng)創(chuàng)建的CALayer對(duì)象,當(dāng)對(duì)非Root Layer的部分屬性進(jìn)行相應(yīng)的修改時(shí),默認(rèn)會(huì)自動(dòng)產(chǎn)生一些動(dòng)畫(huà)效果媳握,這些屬性稱為Animatable Properties(可動(dòng)畫(huà)屬性)碱屁。隱式屬性動(dòng)畫(huà)的本質(zhì)是這些屬性的變動(dòng)默認(rèn)隱含了CABasicAnimation動(dòng)畫(huà)實(shí)現(xiàn),例如修改bounds屬性會(huì)產(chǎn)生縮放動(dòng)畫(huà)蛾找,修改backgroundColor屬性會(huì)產(chǎn)生背景色的漸變動(dòng)畫(huà)娩脾,修改position屬性會(huì)產(chǎn)生平移動(dòng)畫(huà)。

可以通過(guò)動(dòng)畫(huà)事務(wù)(CATransaction)關(guān)閉默認(rèn)的隱式動(dòng)畫(huà)效果
[CATransactionbegin];
[CATransactionsetDisableActions:YES];
self.myview.layer.position= CGPointMake(100, 100);
[CATransactioncommit];

二打毛、簡(jiǎn)單使用

1. 設(shè)置陰影

  imageView.layer.shadowColor = [UIColor grayColor].CGColor;  //陰影顏色
  imageView.layer.shadowOffset = CGSizeMake(10, 10); //陰影偏移量
  imageView.layer.shadowOpacity = 0.5;  //陰影透明度

2.設(shè)置圓角

 imageView.layer.masksToBounds = YES;   
 imageView.layer.cornerRadius = 10;     //當(dāng)cornerRadius等于邊長(zhǎng)的一半時(shí)柿赊,就是圓

3.設(shè)置邊框

 imageView.layer.borderWidth = 5;
 imageView.layer.borderColor = [UIColor redColor].CGColor;

4.設(shè)置旋轉(zhuǎn)

 imageView.layer.transform = CATransform3DMakeRotation(M_PI_4, 0, 0, 1);// 順時(shí)針旋轉(zhuǎn)45

5.繪制圖層

繪制圖層有兩種方法

1.通過(guò)圖層代理drawLayer: inContext:方法繪制
2.通過(guò)自定義圖層drawInContext:方法繪制
不管使用哪種方法繪制完必須調(diào)用圖層的setNeedDisplay方法.

① 使用代理方法繪制圖層
通過(guò)代理方法進(jìn)行圖層繪圖只要指定圖層的代理,然后在代理對(duì)象中重寫-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx方法即可幻枉。需要注意這個(gè)方法雖然是代理方法但是不用手動(dòng)實(shí)現(xiàn)CALayerDelegate碰声,因?yàn)镃ALayer定義中給NSObject做了分類擴(kuò)展,所有的NSObject都包含這個(gè)方法熬甫。另外設(shè)置完代理后必須要調(diào)用圖層的setNeedDisplay方法胰挑,否則繪制的內(nèi)容無(wú)法顯示。

- (void)viewDidLoad {
    [super viewDidLoad];

    CALayer * layer = [[CALayer alloc]init];
    layer.bounds = CGRectMake(0, 0, 100, 100);
    layer.position = CGPointMake(50, 50);
    layer.masksToBounds = YES;
    layer.cornerRadius = 50;
    layer.borderWidth = 2;
    layer.borderColor = [UIColor yellowColor].CGColor;

    layer.delegate = self; //設(shè)置代理
    [self.view.layer addSublayer:layer]; //添加圖層
    [layer setNeedsDisplay]; //重繪
}

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx{
    CGContextSaveGState(ctx);
    CGContextScaleCTM(ctx, 1, -1); //轉(zhuǎn)換坐標(biāo)系
    CGContextTranslateCTM(ctx, 0, -100);
    UIImage * image = [UIImage imageNamed:@"me"];
    CGContextDrawImage(ctx, CGRectMake(0, 0, 100, 100), image.CGImage);
    CGContextRestoreGState(ctx);
}

② 使用自定義圖層繪制圖層
創(chuàng)建一個(gè)CALayer的子類,然后重寫drawInContext:方法,在方法中使用Quartz2D API進(jìn)行繪圖蜀铲;
同樣,使用時(shí)贡这,必須要調(diào)用圖層的setNeedDisplay方法,才會(huì)觸發(fā)drawInContext:方法的調(diào)用厂榛。

Core Animation

一藕坯、簡(jiǎn)介

1.概念

Core Animation 是作用在CALayer上的,使用Core Animation 創(chuàng)建動(dòng)畫(huà)不僅簡(jiǎn)單噪沙,而且還有更好的性能炼彪,因?yàn)镃ore Animation 是在單獨(dú)的線程中完成的,不會(huì)阻塞主線程正歼,而且只會(huì)重繪界面上變化的部分(局部刷新)辐马。

2.分類

類別 說(shuō)明
CAAnimation 所有動(dòng)畫(huà)類的基類,不能直接使用局义,實(shí)現(xiàn)了CAMediaTiming協(xié)議喜爷,提供了動(dòng)畫(huà)的持續(xù)時(shí)間、速度和重復(fù)計(jì)數(shù)等萄唇,還實(shí)現(xiàn)了CAAction協(xié)議檩帐,該協(xié)議為CALayer動(dòng)畫(huà)觸發(fā)的動(dòng)作提供標(biāo)準(zhǔn)化響應(yīng)。
CATransition CAAnimation的子類另萤,轉(zhuǎn)場(chǎng)動(dòng)畫(huà)湃密,能夠?yàn)閷犹峁┮瞥銎聊缓鸵迫肫聊坏膭?dòng)畫(huà)效果
CAAnimationGroup CAAnimation的子類诅挑,動(dòng)畫(huà)組,是一種組合模式設(shè)計(jì)泛源,可以通過(guò)動(dòng)畫(huà)組來(lái)進(jìn)行所有動(dòng)畫(huà)行為的統(tǒng)一控制拔妥,組中所有動(dòng)畫(huà)效果可以并發(fā)執(zhí)行。
CAPropertyAnimation CAAnimation的子類达箍,屬性動(dòng)畫(huà)的基類没龙,通過(guò)控制可動(dòng)畫(huà)屬性慢慢地變化,不能直接使用缎玫。有兩個(gè)子類CABasicAnimation 和 CAKeyframeAnimation硬纤。
CABasicAnimation CAPropertyAnimation 的子類,基礎(chǔ)動(dòng)畫(huà)赃磨,簡(jiǎn)單地控制CALayer層的屬性慢慢改變筝家,從而實(shí)現(xiàn)動(dòng)畫(huà)。
CAKeyframeAnimation CAPropertyAnimation 的子類煞躬,關(guān)鍵幀動(dòng)畫(huà),同樣是通過(guò)屬性進(jìn)行動(dòng)畫(huà)參數(shù)控制逸邦,通過(guò)values屬性指定多個(gè)關(guān)鍵幀恩沛,通過(guò)多個(gè)關(guān)鍵幀可以指定動(dòng)畫(huà)的各階段的關(guān)鍵值。

基礎(chǔ)動(dòng)畫(huà)缕减、關(guān)鍵幀動(dòng)畫(huà)都屬于屬性動(dòng)畫(huà)雷客,是通過(guò)修改屬性值產(chǎn)生動(dòng)畫(huà)效果,只需要設(shè)置初始值和結(jié)束值桥狡,中間的過(guò)程動(dòng)畫(huà)(“補(bǔ)間動(dòng)畫(huà)”)是由系統(tǒng)自動(dòng)計(jì)算產(chǎn)生搅裙。和基礎(chǔ)動(dòng)畫(huà)不同的是關(guān)鍵幀動(dòng)畫(huà)可以設(shè)置多個(gè)屬性值,每?jī)蓚€(gè)屬性中間的補(bǔ)間動(dòng)畫(huà)由系統(tǒng)自動(dòng)完成裹芝,基礎(chǔ)動(dòng)畫(huà)也可以看成是有兩個(gè)關(guān)鍵幀的關(guān)鍵幀動(dòng)畫(huà)部逮。

二、使用

1. CAAnimation

CAAnimation 是基類嫂易,其屬性它的子類也擁有兄朋。它不能直接使用。

屬性 說(shuō)明
beginTime 可以用來(lái)設(shè)置動(dòng)畫(huà)延遲執(zhí)行時(shí)間怜械,若想延遲2s颅和,就設(shè)置為CACurrentMediaTime()+2,CACurrentMediaTime()為圖層的當(dāng)前時(shí)間
duration 動(dòng)畫(huà)的持續(xù)時(shí)間
delegate 動(dòng)畫(huà)代理
repeatCount 重復(fù)次數(shù)缕允,無(wú)限循環(huán)可以設(shè)置HUGE_VALF或者M(jìn)AXFLOAT
repeatDuration 重復(fù)時(shí)間
removedOnCompletion 默認(rèn)為YES峡扩,代表動(dòng)畫(huà)執(zhí)行完畢后就從圖層上移除,圖形會(huì)恢復(fù)到動(dòng)畫(huà)執(zhí)行前的狀態(tài)障本。如果想讓圖層保持顯示動(dòng)畫(huà)執(zhí)行后的狀態(tài)教届,那就設(shè)置為NO,同時(shí)還要設(shè)置fillMode為kCAFillModeForwards
fillMode 決定當(dāng)前對(duì)象在非active時(shí)間段的行為。(要想fillMode有效巍佑,最好設(shè)置removedOnCompletion = NO)茴迁,kCAFillModeRemoved 這個(gè)是默認(rèn)值,也就是說(shuō)當(dāng)動(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)動(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 這個(gè)其實(shí)就是上面兩個(gè)的合成.動(dòng)畫(huà)加入后開(kāi)始之前秦踪,layer便處于動(dòng)畫(huà)初始狀態(tài)褐捻,動(dòng)畫(huà)結(jié)束后layer保持動(dòng)畫(huà)最后的狀態(tài)
timingFunction 速度控制函數(shù),控制動(dòng)畫(huà)運(yùn)行的節(jié)奏椅邓,為 CAMediaTimingFunction 類型柠逞。kCAMediaTimingFunctionLinear(線性):勻速動(dòng)畫(huà);kCAMediaTimingFunctionEaseIn(漸進(jìn)):動(dòng)畫(huà)緩慢進(jìn)入景馁,然后加速離開(kāi)板壮;kCAMediaTimingFunctionEaseOut(漸出):動(dòng)畫(huà)全速進(jìn)入,然后減速的到達(dá)目的地合住;kCAMediaTimingFunctionEaseInEaseOut(漸進(jìn)漸出):動(dòng)畫(huà)緩慢的進(jìn)入绰精,中間加速,然后減速的到達(dá)目的地透葛。

代理方法 : 給NSObject添加了分類笨使,所以任何對(duì)象,都可以成為CAAnimation的代理僚害。

動(dòng)畫(huà)開(kāi)始的時(shí)候調(diào)用 - (void)animationDidStart:(CAAnimation *)anim;
動(dòng)畫(huà)停止的時(shí)候調(diào)用 - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;

2.CAPropertyAnimation

屬性或方法 說(shuō)明
+ (instancetype)animationWithKeyPath:(nullable NSString *)path; 類方法阱表,創(chuàng)建一個(gè)新的動(dòng)畫(huà)對(duì)象,同時(shí)設(shè)置該對(duì)象的keyPath屬性
keyPath 屬性贡珊,用來(lái)描述動(dòng)畫(huà)是作用在哪一個(gè)屬性上
additive 屬性最爬,指定該屬性動(dòng)畫(huà)是否以當(dāng)前動(dòng)畫(huà)效果為基礎(chǔ)
cumulative 屬性,指定動(dòng)畫(huà)是否為累加效果
valueFunction 該屬性值是一個(gè) CAValueFunction 對(duì)象门岔,負(fù)責(zé)對(duì)屬性改變進(jìn)行插值計(jì)算爱致,系統(tǒng)已經(jīng)提供了默認(rèn)的插值計(jì)算方式,一般無(wú)須指定該屬性寒随。

位移動(dòng)畫(huà)通常使用屬性動(dòng)畫(huà)控制 CALayer 的 position 屬性持續(xù)改變糠悯,如果要實(shí)現(xiàn) CALayer 的旋轉(zhuǎn)帮坚、縮放等動(dòng)畫(huà)效果,若在平面上(二維空間)上互艾,則修改 CALayer 的 affineTransform 屬性试和,該屬性值為一個(gè)CGAffineTransform 對(duì)象;若在三維空間上纫普,則修改 CALayer 的 transform 屬性阅悍,該屬性值為一個(gè) CATransform3D 對(duì)象。

CATransform3D : 三維變換矩陣

方法 說(shuō)明
CATransform3DIsIdentity (CATransform3D t) 返回bool值昨稼,判斷 t 矩陣是否為單位矩陣
CATransform3DEqualToTransform (CATransform3D a, CATransform3D b) 返回bool值节视,判斷 a , b 兩個(gè)矩陣是否相等
CATransform3DMakeTranslation (CGFloat tx, CGFloat ty, CGFloat tz) 創(chuàng)建一個(gè)在X方向上移動(dòng) tx、在Y方向上移動(dòng) ty假栓、在Z方向上移動(dòng) tz 的變化矩陣
CATransform3DMakeScale (CGFloat sx, CGFloat sy, CGFloat sz) 創(chuàng)建一個(gè)在X方向上縮放 sx寻行、在Y方向上縮放 sy、在Z方向上縮放 sz 的變化矩陣
CATransform3DMakeRotation (CGFloat angle, CGFloat x, CGFloat y, CGFloat z) 創(chuàng)建基于指定旋轉(zhuǎn)軸旋轉(zhuǎn) angle 弧度的變換匾荆,x拌蜘、y、z 用于確定旋轉(zhuǎn)軸牙丽,(1简卧,0,0)指定旋轉(zhuǎn)軸為X軸剩岳,(0贞滨,1入热,0)指定旋轉(zhuǎn)軸為Y軸拍棕,(0,0勺良,1)指定旋轉(zhuǎn)軸為Z軸
CATransform3DTranslate (CATransform3D t, CGFloat tx, CGFloat ty, CGFloat tz) 在 t 變化矩陣的基礎(chǔ)上進(jìn)行位移變換
CATransform3DScale (CATransform3D t, CGFloat sx, CGFloat sy, CGFloat sz) 在 t 變化矩陣的基礎(chǔ)上進(jìn)行縮放變換
CATransform3DRotate (CATransform3D t, CGFloat angle, CGFloat x, CGFloat y, CGFloat z) 在 t 變化矩陣的基礎(chǔ)上進(jìn)行旋轉(zhuǎn)變換
CATransform3DConcat (CATransform3D a, CATransform3D b) 將a绰播,b兩個(gè)矩陣相乘
CATransform3DInvert (CATransform3D t) 對(duì) t 矩形進(jìn)行反轉(zhuǎn)
CATransform3DMakeAffineTransform (CGAffineTransform m) 將 CGAffineTransform 矩陣轉(zhuǎn)化成 CATransform3D 矩陣,轉(zhuǎn)化后也只有X尚困,Y維度上的變換
CATransform3DIsAffine (CATransform3D t) 返回bool值蠢箩,判斷 t 矩陣是否是 CGAffineTransform 變換矩陣
CATransform3DGetAffineTransform (CATransform3D t) 獲取 t 矩陣所包含的 CGAffineTransform 變換矩陣

3.CABasicAnimation 和 CAKeyframeAnimation

CAPropertyAnimation的子類,首先創(chuàng)建初始化一個(gè)CALayer事甜,初始化動(dòng)畫(huà)CABasicAnimation是設(shè)置 fromValue 和 toValue 谬泌,CAKeyframeAnimation是設(shè)置 values ,再設(shè)置其他動(dòng)畫(huà)屬性逻谦,將動(dòng)畫(huà)添加到圖層上掌实。

CALayer 為動(dòng)畫(huà)提供的方法

方法 說(shuō)明
- (void)addAnimation:(CAAnimation *)anim forKey:(nullable NSString *)key 為 CALayer 添加一個(gè)動(dòng)畫(huà),并為動(dòng)畫(huà)指定一個(gè)唯一標(biāo)識(shí)
- (nullable CAAnimation *)animationForKey:(NSString *)key 讓 CALayer 執(zhí)行 key 所對(duì)應(yīng)的動(dòng)畫(huà)
- (void)removeAllAnimations 刪除 CALayer 上添加的所有動(dòng)畫(huà)
- (void)removeAnimationForKey:(NSString *)key 刪除 key 所對(duì)應(yīng)的動(dòng)畫(huà)
- (nullable NSArray<NSString *> *)animationKeys 獲取 CALayer 上所有動(dòng)畫(huà)的 key 組成的數(shù)組

① 位移動(dòng)畫(huà)
CABasicAnimation

CABasicAnimation * anim = [CABasicAnimation animationWithKeyPath:@"position"];
anim.fromValue = [NSValue valueWithCGPoint:self.layer.position];
CGPoint toPoint = CGPointMake(300, 300);
anim.toValue = [NSValue valueWithCGPoint:toPoint];
anim.duration = 1.0;
self.layer.position = toPoint;
anim.removedOnCompletion = YES;
[self.layer addAnimation:anim forKey:@"KCBasicAnimation_Position"];

CAKeyframeAnimation

CAKeyframeAnimation * keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
NSValue * value1 = [NSValue valueWithCGPoint:self.layer.position];
NSValue * value2 = [NSValue valueWithCGPoint:CGPointMake(80, 220)];
NSValue * value3 = [NSValue valueWithCGPoint:CGPointMake(45, 300)];
NSValue * value4 = [NSValue valueWithCGPoint:CGPointMake(55, 400)];
NSArray * values=@[value1,value2,value3,value4];
keyframeAnimation.values = values;
keyframeAnimation.duration = 2.0;
[self.layer addAnimation:keyframeAnimation forKey:@"KCKeyframeAnimation_Position"];    

通過(guò)描繪路徑進(jìn)行關(guān)鍵幀動(dòng)畫(huà)控制

CAKeyframeAnimation * keyframeAnimation=[CAKeyframeAnimation animationWithKeyPath:@"position"];
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, self.layer.position.x, self.layer.position.y);
CGPathAddCurveToPoint(path, NULL, 160, 280, -30, 300, 55, 400);
keyframeAnimation.path = path;
CGPathRelease(path);
keyframeAnimation.duration = 4.0;
keyframeAnimation.removedOnCompletion = YES;
[self.layer addAnimation:keyframeAnimation forKey:@"KCKeyframeAnimation_Position"];

② 旋轉(zhuǎn)動(dòng)畫(huà)
CABasicAnimation

CABasicAnimation * anim = [CABasicAnimation animationWithKeyPath:@"transform"];
CATransform3D fromValue = self.layer.transform;
anim.fromValue = [NSValue valueWithCATransform3D:fromValue];
CATransform3D toValue = CATransform3DRotate(fromValue, M_PI, 1, 0, 0);
anim.toValue = [NSValue valueWithCATransform3D:toValue];
anim.duration = 0.5;
self.layer.transform = toValue;
anim.removedOnCompletion = YES;
[self.layer addAnimation:anim forKey:@"KCBasicAnimation_Rotate"];

CAKeyframeAnimation

CAKeyframeAnimation * keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
NSValue * value1 = [NSValue valueWithCATransform3D:self.layer.transform];
NSValue * value2 = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI, 1, 0, 0)];
NSValue * value3 = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI, 0, 1, 0)];
NSValue * value4 = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI, 0, 0, 1)];
NSArray * values = @[value1,value2,value3,value4];
keyframeAnimation.values = values;
keyframeAnimation.duration = 2.0;
[self.layer addAnimation:keyframeAnimation forKey:@"KCKeyframeAnimation_Rotate"];

③ 縮放動(dòng)畫(huà)
CABasicAnimation

CABasicAnimation * anim = [CABasicAnimation animationWithKeyPath:@"transform"];
CATransform3D fromValue = self.layer.transform;
anim.fromValue = [NSValue valueWithCATransform3D:fromValue];
CATransform3D toValue = CATransform3DScale(fromValue, 0.5, 0.5, 1);
anim.toValue = [NSValue valueWithCATransform3D:toValue];
anim.duration = 0.5;
self.layer.transform = toValue;
anim.removedOnCompletion = YES;
[self.layer addAnimation:anim forKey:@"KCBasicAnimation_Scale"];

CAKeyframeAnimation

CAKeyframeAnimation * keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
NSValue * value1 = [NSValue valueWithCATransform3D:self.layer.transform];
NSValue * value2 = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.5, 0.5, 1)];
NSValue * value3 = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1, 1, 1)];
NSArray * values = @[value1,value2,value3];
keyframeAnimation.values = values;
keyframeAnimation.duration = 2.0;
[self.layer addAnimation:keyframeAnimation forKey:@"KCKeyframeAnimation_Scale"];

④ 動(dòng)畫(huà)組
CABasicAnimation

CGPoint fromPoint = self.layer.position;
CGPoint toPoint = CGPointMake(280, fromPoint.y + 300);

CABasicAnimation * moveAnim = [CABasicAnimation animationWithKeyPath:@"position"];
moveAnim.fromValue = [NSValue valueWithCGPoint:fromPoint];
moveAnim.toValue = [NSValue valueWithCGPoint:toPoint];
moveAnim.removedOnCompletion = YES;

CABasicAnimation * transformAnim = [CABasicAnimation animationWithKeyPath:@"transform"];
CATransform3D fromValue = self.layer.transform;
transformAnim.fromValue = [NSValue valueWithCATransform3D:fromValue];
CATransform3D scaleValue = CATransform3DScale(fromValue, 0.5, 0.5, 1);
CATransform3D rotateValue = CATransform3DRotate(fromValue, M_PI, 0, 0, 1);
CATransform3D toValue = CATransform3DConcat(scaleValue, rotateValue);
transformAnim.toValue = [NSValue valueWithCATransform3D:toValue];
transformAnim.cumulative = YES;
transformAnim.repeatCount = 2;
transformAnim.duration = 3;

CAAnimationGroup * animGroup = [CAAnimationGroup animation];
animGroup.animations = @[moveAnim,transformAnim];
animGroup.duration = 6;
[self.layer addAnimation:animGroup forKey:@"KCBasicAnimation_Group"];

CAKeyframeAnimation

CAKeyframeAnimation * moveAnim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
NSValue * move1 = [NSValue valueWithCGPoint:self.layer.position];
NSValue * move2 = [NSValue valueWithCGPoint:CGPointMake(300, 100)];
NSValue * move3 = [NSValue valueWithCGPoint:CGPointMake(300, 300)];
NSValue * move4 = [NSValue valueWithCGPoint:CGPointMake(100, 300)];
NSValue * move5 = [NSValue valueWithCGPoint:CGPointMake(100, 100)];
NSArray * values = @[move1,move2,move3,move4,move5];
moveAnim.values = values;
moveAnim.removedOnCompletion = YES;

CAKeyframeAnimation * transformAnim = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
CATransform3D rotate1 = self.layer.transform;
CATransform3D rotate2 = CATransform3DMakeRotation(M_PI, 1, 0, 0);
CATransform3D rotate3 = CATransform3DMakeRotation(M_PI, 0, 1, 0);
CATransform3D rotate4 = CATransform3DMakeRotation(M_PI, 0, 0, 1);
CATransform3D rotate5 = CATransform3DMakeRotation(M_PI, 1, 1, 1);

CATransform3D scale1 = self.layer.transform;
CATransform3D scale2 = CATransform3DMakeScale(0.5, 0.5, 1);
CATransform3D scale3 = CATransform3DMakeScale(1, 1, 1);
CATransform3D scale4 = CATransform3DMakeScale(0.5, 0.5, 1);
CATransform3D scale5 = CATransform3DMakeScale(1, 1, 1);

NSValue * transform1 = [NSValue valueWithCATransform3D:CATransform3DConcat(rotate1, scale1)];
NSValue * transform2 = [NSValue valueWithCATransform3D:CATransform3DConcat(rotate2, scale2)];
NSValue * transform3 = [NSValue valueWithCATransform3D:CATransform3DConcat(rotate3, scale3)];
NSValue * transform4 = [NSValue valueWithCATransform3D:CATransform3DConcat(rotate4, scale4)];
NSValue * transform5 = [NSValue valueWithCATransform3D:CATransform3DConcat(rotate5, scale5)];
transformAnim.values = @[transform1,transform2,transform3,transform4,transform5];
transformAnim.removedOnCompletion = YES;

CAAnimationGroup * animGroup = [CAAnimationGroup animation];
animGroup.animations = @[moveAnim,transformAnim];
animGroup.duration = 8;
self.layer.position = CGPointMake(100, 100);
[self.layer addAnimation:animGroup forKey:@"KCBasicAnimation_Group"];

④ 動(dòng)畫(huà)暫停

-(void)pauseLayer{
    CFTimeInterval interval=[self.layer convertTime:CACurrentMediaTime() fromLayer:nil];
    [self.layer setTimeOffset:interval];
    self.layer.speed=0;
}

⑤ 動(dòng)畫(huà)恢復(fù)

-(void)resumeLayer{
    CFTimeInterval beginTime= CACurrentMediaTime() - self.layer.timeOffset;
    self.layer.timeOffset = 0;
    self.layer.beginTime = beginTime;
    self.layer.speed=1.0;
}

4.CATransition

屬性 說(shuō)明
type 動(dòng)畫(huà)過(guò)渡效果
subtype 動(dòng)畫(huà)過(guò)渡方向
startProgress 動(dòng)畫(huà)起點(diǎn)(在整體動(dòng)畫(huà)的百分比)
endProgress 動(dòng)畫(huà)終點(diǎn)(在整體動(dòng)畫(huà)的百分比)

CATransition的type屬性用于控制動(dòng)畫(huà)類型邦马,還有私有動(dòng)畫(huà)贱鼻。

值| 說(shuō)明 |是否支持方向設(shè)置
-----|-----
kCATransitionFade|通過(guò)漸隱效果過(guò)渡宴卖,默認(rèn)屬性值|是
kCATransitionMoveIn|通過(guò)移入動(dòng)畫(huà)過(guò)渡,新視圖移到舊視圖上面|是
kCATransitionPush|通過(guò)推入動(dòng)畫(huà)過(guò)渡邻悬,新視圖把舊視圖推出去|是
kCATransitionReveal|通過(guò)揭開(kāi)動(dòng)畫(huà)過(guò)渡症昏,將舊視圖移開(kāi),同時(shí)顯示下面的新視圖|是
@"cube"|通過(guò)立方體旋轉(zhuǎn)動(dòng)畫(huà)過(guò)渡|是
@"oglFlip"|通過(guò)翻轉(zhuǎn)動(dòng)畫(huà)過(guò)渡|是
@"suckEffect"|通過(guò)收縮(吸入)動(dòng)畫(huà)過(guò)渡|否
@"rippleEffect"|通過(guò)水波動(dòng)畫(huà)過(guò)渡|否
@"pageCurl"|通過(guò)向后翻頁(yè)動(dòng)畫(huà)過(guò)渡|是
@"pageUnCurl"|通過(guò)向前翻頁(yè)動(dòng)畫(huà)過(guò)渡|是
@"cameraIrisHollowOpen"|通過(guò)相機(jī)鏡頭打開(kāi)效果動(dòng)畫(huà)過(guò)渡|否
@"cameraIrisHollowClose"|通過(guò)相機(jī)鏡頭關(guān)閉效果動(dòng)畫(huà)過(guò)渡|否

CATransition的subtype屬性用于控制動(dòng)畫(huà)方向

說(shuō)明
kCATransitionFromRight 從右側(cè)轉(zhuǎn)場(chǎng)
kCATransitionFromLeft 從左側(cè)轉(zhuǎn)場(chǎng)
kCATransitionFromTop 從頂部轉(zhuǎn)場(chǎng)
kCATransitionFromBottom 從底部轉(zhuǎn)場(chǎng)
#import "ViewController.h"
#define IMAGE_COUNT 5

typedef enum {
    GestureDirectionUp = 1,
    GestureDirectionDown,
    GestureDirectionLeft,
    GestureDirectionRight
}GestureDirection;

@interface ViewController () <UIPickerViewDelegate,UIPickerViewDataSource>

@property (nonatomic,strong) UIImageView * imageView;
@property (nonatomic,assign) int currentIndex;
@property (nonatomic,strong) CATransition * transition;
@property (nonatomic,strong) UIPickerView * pickerView;
@property (nonatomic,copy) NSArray * transitions;
@property (nonatomic,assign) BOOL isPop;

@end

@implementation ViewController

- (NSArray *)transitions{
    if (_transitions == nil) {
        _transitions = @[kCATransitionFade,kCATransitionMoveIn,kCATransitionPush,kCATransitionReveal,@"cube",@"oglFlip",@"suckEffect",@"rippleEffect",@"pageCurl",@"pageUnCurl",@"cameralIrisHollowOpen",@"cameraIrisHollowClose"];
    }
    return _transitions;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor whiteColor];

    CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
    CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;

    self.navigationItem.title = @"轉(zhuǎn)場(chǎng)";
    UIBarButtonItem * rightBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"效果" style:UIBarButtonItemStyleDone target:self action:@selector(selectTransition:)];
    self.navigationItem.rightBarButtonItem = rightBarButtonItem;

    self.imageView = [[UIImageView alloc]initWithFrame:self.view.frame];
    self.imageView.backgroundColor = [UIColor whiteColor];
    self.imageView.contentMode = UIViewContentModeScaleAspectFit;
    self.imageView.image = [UIImage imageNamed:@"0.jpg"];
    [self.view addSubview:self.imageView];

    self.pickerView = [[UIPickerView alloc]initWithFrame:CGRectMake(0, screenHeight, screenWidth, 300)];
    self.pickerView.dataSource = self;
    self.pickerView.delegate = self;
    [self.view addSubview:self.pickerView];

    UISwipeGestureRecognizer * upSwipeGesture = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipe:)];
    [upSwipeGesture setDirection:UISwipeGestureRecognizerDirectionUp];
    [self.view addGestureRecognizer:upSwipeGesture];

    UISwipeGestureRecognizer * downSwipeGesture = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipe:)];
    [downSwipeGesture setDirection:UISwipeGestureRecognizerDirectionDown];
    [self.view addGestureRecognizer:downSwipeGesture];

    UISwipeGestureRecognizer * leftSwipeGesture = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipe:)];
    [leftSwipeGesture setDirection:UISwipeGestureRecognizerDirectionLeft];
    [self.view addGestureRecognizer:leftSwipeGesture];

    UISwipeGestureRecognizer * rightSwipeGesture = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipe:)];
    [rightSwipeGesture setDirection:UISwipeGestureRecognizerDirectionRight];
    [self.view addGestureRecognizer:rightSwipeGesture];

    self.transition = [[CATransition alloc]init];
    self.transition.type = kCATransitionFade;
    self.isPop = NO;
}

- (void)selectTransition:(UIBarButtonItem *)btn{
    self.isPop = !self.isPop;
    if (self.isPop) {
        CGContextRef context = UIGraphicsGetCurrentContext();
        [UIView beginAnimations:nil context:context];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
        [UIView setAnimationDuration:0.6];
        [self.view bringSubviewToFront:self.pickerView];
        CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
        CGFloat pickerViewWidth = [UIScreen mainScreen].bounds.size.width;
        CGFloat pickerViewHeight = 300;
        self.pickerView.frame = CGRectMake(0, screenHeight - pickerViewHeight, pickerViewWidth, pickerViewHeight);
        [UIView commitAnimations];
}
else {
        CGContextRef context = UIGraphicsGetCurrentContext();
        [UIView beginAnimations:nil context:context];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
        [UIView setAnimationDuration:0.6];
        CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
        CGFloat pickerViewWidth = [UIScreen mainScreen].bounds.size.width;
        CGFloat pickerViewHeight = 300;
        self.pickerView.frame = CGRectMake(0, screenHeight, pickerViewWidth, pickerViewHeight);
        [UIView commitAnimations];
    }
}

-(void)swipe:(UISwipeGestureRecognizer *)gesture{
    if (gesture.direction == UISwipeGestureRecognizerDirectionUp){
        [self transitionAnimation:GestureDirectionUp];
    }
    else if (gesture.direction == UISwipeGestureRecognizerDirectionDown){
        [self transitionAnimation:GestureDirectionDown];
    }
    else if (gesture.direction == UISwipeGestureRecognizerDirectionLeft){
        [self transitionAnimation:GestureDirectionLeft];
    }
    else {
        [self transitionAnimation:GestureDirectionRight];
    }
}

- (void)transitionAnimation:(GestureDirection)gestureDirection{
    switch (gestureDirection) {
        case GestureDirectionUp:
            self.transition.subtype = kCATransitionFromTop;
            break;
        case GestureDirectionDown:
            self.transition.subtype = kCATransitionFromBottom;
           break;
        case GestureDirectionLeft:
            self.transition.subtype = kCATransitionFromRight;
            break;
        case GestureDirectionRight:
            self.transition.subtype = kCATransitionFromLeft;
            break;
        default:
            break;
    }
    self.transition.duration = 1.0f;
    self.imageView.image = [self getImage];
    [self.view.layer addAnimation:self.transition forKey:@"KCTransitionAnimation"];
}

- (UIImage *)getImage{
    self.currentIndex = (self.currentIndex + 1) % IMAGE_COUNT;
    NSString *imageName=[NSString stringWithFormat:@"%i.jpg",_currentIndex];
    return [UIImage imageNamed:imageName];
}

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
    return 1;
}

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
    return self.transitions.count;
}

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{
    return self.transitions[row];
}

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
    self.transition.type = self.transitions[row];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

5.逐幀動(dòng)畫(huà)

通過(guò)設(shè)置UIImageView的animationImages屬性,然后調(diào)用它的startAnimating方法去播放一組逐幀圖片父丰,但是它存在著很大的性能問(wèn)題肝谭,并且這種方法一旦設(shè)置完圖片中間的過(guò)程就無(wú)法控制了。使用CADisplayLink加入到主循環(huán)隊(duì)列中础米,循環(huán)調(diào)用目標(biāo)方法分苇,在這個(gè)方法中更新視圖內(nèi)容就可以完成逐幀動(dòng)畫(huà)。

- (void)runAnimationWithImageCount:(NSInteger)count AndImageName:(NSString *)name
{
    if (self.myImageView.isAnimating)
    {
        return;
    }
    NSMutableArray * pictArray = [NSMutableArray array];
    for (int i = 0; i < count; i++)
    {
        NSString * pictNum = [NSString stringWithFormat:@"%@_%02d.jpg",name,i];
        // 使用imageNamed的方式加載圖片會(huì)有緩存屁桑,使得占用的內(nèi)存很大
        //[pictArray addObject:[UIImage imageNamed:pictNum]];
    
        // 直接從文件中讀取圖片就不會(huì)占用太大的內(nèi)存
        NSBundle * boudle = [NSBundle mainBundle];
        NSString * path = [boudle pathForResource:pictNum ofType:nil];
        [pictArray addObject:[UIImage imageWithContentsOfFile:path]];
    }
    self.myImageView.animationImages = pictArray;
    self.myImageView.animationDuration = (self.myImageView.animationImages.count * 0.07);
    CGFloat delayTime = self.myImageView.animationDuration + 0.5;
    self.myImageView.animationRepeatCount = 1;
    [self.myImageView startAnimating];

    [self.myImageView performSelector:@selector(setAnimationImages:) withObject:nil afterDelay:delayTime];
}

6.UIView動(dòng)畫(huà)封裝

UIView本身對(duì)于基本動(dòng)畫(huà)和關(guān)鍵幀動(dòng)畫(huà)医寿、轉(zhuǎn)場(chǎng)動(dòng)畫(huà)都有相應(yīng)的封裝。

方法 說(shuō)明
+ (void)beginAnimations:(nullable NSString *)animationID context:(nullable void *)context 開(kāi)始動(dòng)畫(huà)蘑斧,animationID :動(dòng)畫(huà)塊內(nèi)部應(yīng)用程序標(biāo)識(shí)靖秩,context :附加的信息,都傳遞給動(dòng)畫(huà)代理
+ (void)commitAnimations 提交動(dòng)畫(huà)竖瘾,結(jié)束動(dòng)畫(huà)
+ (void)setAnimationDelegate:(nullable id)delegate 設(shè)置動(dòng)畫(huà)的代理
+ (void)setAnimationWillStartSelector:(nullable SEL)selector 設(shè)置動(dòng)畫(huà)開(kāi)始時(shí)的執(zhí)行方法
+ (void)setAnimationDidStopSelector:(nullable SEL)selector 設(shè)置動(dòng)畫(huà)結(jié)束時(shí)的執(zhí)行方法
+ (void)setAnimationDuration:(NSTimeInterval)duration 設(shè)置動(dòng)畫(huà)執(zhí)行時(shí)間
+ (void)setAnimationDelay:(NSTimeInterval)delay 設(shè)置動(dòng)畫(huà)延遲執(zhí)行的時(shí)間
+ (void)setAnimationStartDate:(NSDate *)startDate 設(shè)置動(dòng)畫(huà)開(kāi)始執(zhí)行的時(shí)間
+ (void)setAnimationCurve:(UIViewAnimationCurve)curve 設(shè)置動(dòng)畫(huà)運(yùn)行過(guò)程中相對(duì)的速度
+ (void)setAnimationRepeatCount:(float)repeatCount 設(shè)置動(dòng)畫(huà)重復(fù)次數(shù)
+ (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses 設(shè)置是否自動(dòng)逆向動(dòng)畫(huà)
+ (void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState 設(shè)置動(dòng)畫(huà)是否從當(dāng)前狀態(tài)開(kāi)始執(zhí)行沟突,設(shè)置為YES,則當(dāng)上一次動(dòng)畫(huà)正在執(zhí)行中捕传,那么當(dāng)下一個(gè)動(dòng)畫(huà)開(kāi)始時(shí)惠拭,上一次動(dòng)畫(huà)的當(dāng)前狀態(tài)將成為下一次動(dòng)畫(huà)的開(kāi)始狀態(tài)。設(shè)置為NO庸论,則當(dāng)上一個(gè)動(dòng)畫(huà)正在執(zhí)行中职辅,那么當(dāng)下一個(gè)動(dòng)畫(huà)開(kāi)始時(shí),上一次動(dòng)畫(huà)需要先恢復(fù)到完成時(shí)的狀態(tài)聂示,然后在開(kāi)始執(zhí)行下一次動(dòng)畫(huà)
+ (void)setAnimationsEnabled:(BOOL)enabled 設(shè)置動(dòng)畫(huà)是否可用
+ (BOOL)areAnimationsEnabled 獲取動(dòng)畫(huà)是否可用

動(dòng)畫(huà)使用block方式

方法 說(shuō)明
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations 使用block方式
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion 使用block方式域携,有完成后的block
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion 使用block方式,可以設(shè)置動(dòng)畫(huà)延遲時(shí)間和動(dòng)畫(huà)參數(shù)
+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))animations completion:(void (^ __nullable)(BOOL finished))completion 轉(zhuǎn)場(chǎng)動(dòng)畫(huà)
+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^ __nullable)(BOOL finished))completion 轉(zhuǎn)場(chǎng)動(dòng)畫(huà)鱼喉,toView添加到fromView的父視圖中秀鞭,fromView從它的福視圖中移除
+ (void)animateKeyframesWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewKeyframeAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion 使用block方式實(shí)現(xiàn)關(guān)鍵幀動(dòng)畫(huà)
+ (void)addKeyframeWithRelativeStartTime:(double)frameStartTime relativeDuration:(double)frameDuration animations:(void (^)(void))animations 從開(kāi)始時(shí)間添加一個(gè)持續(xù)時(shí)間的動(dòng)畫(huà)

UIViewAnimationCurve

說(shuō)明
UIViewAnimationCurveEaseIn 先慢后快,在動(dòng)畫(huà)剛開(kāi)始的時(shí)候執(zhí)行速度慢
UIViewAnimationCurveEaseOut 先快后慢扛禽,在動(dòng)畫(huà)快結(jié)束的時(shí)候執(zhí)行速度慢
UIViewAnimationCurveEaseInOut 先由慢變快锋边,然后再變慢,在動(dòng)畫(huà)剛開(kāi)始和快結(jié)束的時(shí)候速度慢
UIViewAnimationCurveLinear 勻速運(yùn)行

UIViewAnimationOptions

說(shuō)明
UIViewAnimationOptionLayoutSubviews 動(dòng)畫(huà)過(guò)程中保證子視圖跟隨運(yùn)動(dòng)
UIViewAnimationOptionAllowUserInteraction 動(dòng)畫(huà)過(guò)程中允許用戶交互
UIViewAnimationOptionBeginFromCurrentState 所有視圖從當(dāng)前狀態(tài)開(kāi)始運(yùn)行
UIViewAnimationOptionRepeat 重復(fù)執(zhí)行動(dòng)畫(huà)
UIViewAnimationOptionAutoreverse 逆向動(dòng)畫(huà)编曼,動(dòng)畫(huà)運(yùn)行到結(jié)束點(diǎn)后仍然以動(dòng)畫(huà)方式回到初始點(diǎn)
UIViewAnimationOptionOverrideInheritedDuration 忽略嵌套動(dòng)畫(huà)時(shí)間設(shè)置
UIViewAnimationOptionOverrideInheritedCurve 忽略嵌套動(dòng)畫(huà)速度設(shè)置
UIViewAnimationOptionAllowAnimatedContent 動(dòng)畫(huà)過(guò)程允許重繪視圖(僅適用在轉(zhuǎn)場(chǎng)動(dòng)畫(huà)中)
UIViewAnimationOptionShowHideTransitionViews 視圖切換時(shí)翻轉(zhuǎn)隱藏舊視圖豆巨、顯示新視圖,而不再是直接刪除舊視圖灵巧、添加新視圖
UIViewAnimationOptionOverrideInheritedOptions 不繼承任何參數(shù)或動(dòng)畫(huà)類型
UIViewAnimationOptionCurveEaseInOut 默認(rèn)值搀矫,和UIViewAnimationCurveEaseInOut效果一樣抹沪,只是這個(gè)值用于block動(dòng)畫(huà)參數(shù),先由慢變快瓤球,然后再變慢融欧,在動(dòng)畫(huà)剛開(kāi)始和快結(jié)束的時(shí)候速度慢
UIViewAnimationOptionCurveEaseIn 和UIViewAnimationCurveEaseIn效果一樣,先慢后快卦羡,在動(dòng)畫(huà)剛開(kāi)始的時(shí)候執(zhí)行速度慢
UIViewAnimationOptionCurveEaseOut 和UIViewAnimationCurveEaseOut效果一樣噪馏,先快后慢,在動(dòng)畫(huà)快結(jié)束的時(shí)候執(zhí)行速度慢
UIViewAnimationOptionCurveLinear 和UIViewAnimationCurveLinear效果一樣绿饵,勻速運(yùn)行
UIViewAnimationOptionTransitionNone 下面的值僅適用于轉(zhuǎn)場(chǎng)動(dòng)畫(huà)設(shè)置欠肾,沒(méi)有轉(zhuǎn)場(chǎng)動(dòng)畫(huà)效果
UIViewAnimationOptionTransitionFlipFromLeft 從左側(cè)翻轉(zhuǎn)
UIViewAnimationOptionTransitionFlipFromRight 從右側(cè)翻轉(zhuǎn)
UIViewAnimationOptionTransitionCurlUp 向后翻頁(yè)的動(dòng)畫(huà)過(guò)渡
UIViewAnimationOptionTransitionCrossDissolve 水波動(dòng)畫(huà)過(guò)渡
UIViewAnimationOptionTransitionFlipFromTop 從頂部翻轉(zhuǎn)
UIViewAnimationOptionTransitionFlipFromBottom 從底部翻轉(zhuǎn)

UIViewKeyframeAnimationOptions
其中一部分值和 UIViewAnimationOptions 是一樣的,不一樣的如下:

說(shuō)明
UIViewKeyframeAnimationOptionCalculationModeLinear 連續(xù)運(yùn)算模式
UIViewKeyframeAnimationOptionCalculationModeDiscrete 離散運(yùn)算模式
UIViewKeyframeAnimationOptionCalculationModePaced 均勻執(zhí)行運(yùn)算模式
UIViewKeyframeAnimationOptionCalculationModeCubic 平滑運(yùn)算模式
UIViewKeyframeAnimationOptionCalculationModeCubicPaced 平滑均勻運(yùn)算模式

7.彈簧動(dòng)畫(huà)

方法 說(shuō)明
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion UIViewAnimationWithBlocks中的方法拟赊,用來(lái)創(chuàng)建具有彈簧效果的動(dòng)畫(huà)刺桃。dampingRatio為阻尼,范圍0~1吸祟,阻尼越接近于0瑟慈,彈性效果越明顯。velocity為彈性復(fù)位的速度屋匕。
[UIView animateWithDuration:5.0 delay:0 usingSpringWithDamping:0.1 initialSpringVelocity:1.0 options:UIViewAnimationOptionCurveLinear animations:^{
    self.imageView.center = CGPointMake(300, 300);
} completion:nil];
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末葛碧,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子过吻,更是在濱河造成了極大的恐慌进泼,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纤虽,死亡現(xiàn)場(chǎng)離奇詭異乳绕,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)廓推,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門刷袍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)翩隧,“玉大人樊展,你說(shuō)我怎么就攤上這事《焉” “怎么了专缠?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)淑仆。 經(jīng)常有香客問(wèn)我涝婉,道長(zhǎng),這世上最難降的妖魔是什么蔗怠? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任墩弯,我火速辦了婚禮吩跋,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘渔工。我一直安慰自己锌钮,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布引矩。 她就那樣靜靜地躺著梁丘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪旺韭。 梳的紋絲不亂的頭發(fā)上氛谜,一...
    開(kāi)封第一講書(shū)人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音区端,去河邊找鬼值漫。 笑死,一個(gè)胖子當(dāng)著我的面吹牛织盼,可吹牛的內(nèi)容都是我干的惭嚣。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼悔政,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼晚吞!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起谋国,我...
    開(kāi)封第一講書(shū)人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤槽地,失蹤者是張志新(化名)和其女友劉穎阻逮,沒(méi)想到半個(gè)月后慨丐,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體芒粹,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡廉白,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年沉删,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了壳鹤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片魔吐。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡弯汰,死狀恐怖祷愉,靈堂內(nèi)的尸體忽然破棺而出窗宦,到底是詐尸還是另有隱情,我是刑警寧澤二鳄,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布赴涵,位于F島的核電站,受9級(jí)特大地震影響订讼,放射性物質(zhì)發(fā)生泄漏髓窜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一欺殿、第九天 我趴在偏房一處隱蔽的房頂上張望寄纵。 院中可真熱鬧鳖敷,春花似錦、人聲如沸程拭。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)哺壶。三九已至屋吨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間山宾,已是汗流浹背至扰。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留资锰,地道東北人敢课。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像绷杜,于是被迫代替她去往敵國(guó)和親直秆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容