iOS動畫

相關(guān)或者無關(guān)的

layer

Layers Provide the Basis for Drawing and Animations(Layers是繪圖和動畫的基礎(chǔ))

Layer是在3D空間中的2D平面,管理幾何(例如rotate谋国,transform)槽地,內(nèi)容(image等),和可視屬性(backgroundColor芦瘾,alpha)等信息捌蚊。因?yàn)閳D層主要用來管理數(shù)據(jù),可以看作對象模型近弟,
由于基于Layer的繪制是處理靜態(tài)的Bitmap的缅糟,而bitmap的處理又是GPU所擅長的,所以它的效率要比基于View繪制的高很多祷愉,因?yàn)榛赩iew繪制的每次都要進(jìn)行drawRect的調(diào)用重新繪制窗宦。
大部分圖層,捕獲顯示的內(nèi)容并緩存它們到位圖中二鳄。位圖有時(shí)也被稱為儲備(backing store)赴涵。當(dāng)你改變了一個(gè)圖層的屬性值,只是改變了與圖層對象相關(guān)聯(lián)的狀態(tài)信息订讼。當(dāng)更改觸發(fā)了一個(gè)動畫句占,Core Animation會將該圖層的位圖數(shù)據(jù)和狀態(tài)信息發(fā)送給圖形處理硬件。圖形處理器所做的工作是根據(jù)獲得的信息對位圖進(jìn)行渲染躯嫉,用圖形處理硬件操縱位圖要比圖形處理軟件能獲得更好的動畫效果。

基于Layer的動畫過程

因?yàn)椴倏v的是靜態(tài)的位圖杨拐,基于Layer的繪圖和基于View的繪圖在技術(shù)上有明顯的不同祈餐。
基于View的繪圖,對View的改變經(jīng)常會觸發(fā)視圖的drawRect:方法以重繪視圖內(nèi)容哄陶。但代價(jià)相對較高帆阳,因?yàn)樗荂PU在主線程上的操作。
Core Animation盡可能使用圖形硬件操縱緩存后的位圖來避免了這種開銷,從而完成相同或相似的效果蜒谤。雖然盡可能使用緩存內(nèi)容山宾,但也必須提供初始內(nèi)容并不時(shí)地進(jìn)行內(nèi)容更新。

圖層對象定義了自己的幾何結(jié)構(gòu)
圖層的一項(xiàng)任務(wù)是管理自身內(nèi)容的幾何結(jié)構(gòu)鳍徽。包含內(nèi)容的邊界bound资锰、在屏幕上的位置origin,是否已被旋轉(zhuǎn)阶祭、縮放绷杜,或應(yīng)用了某種變換。圖層有frame和bound屬性來定位圖層和它的內(nèi)容濒募。也有一些View所沒有的屬性鞭盟,比如anchorPoint屬性,任何變換操作都是圍繞該點(diǎn)運(yùn)轉(zhuǎn)的

圖層可在三維空間中操作
Layer有兩個(gè)操控圖層和內(nèi)容的變換矩陣瑰剃,transformsublayerTransform屬性齿诉。

  • transform指定應(yīng)用到圖層和它內(nèi)嵌的子層上的變換。當(dāng)你想更改圖層本身則使用該屬性晌姚。
    比方說粤剧,使用該屬性縮放或旋轉(zhuǎn)圖層,或臨時(shí)的改變圖層的位置舀凛。

  • sublayerTransform屬性定義了僅應(yīng)用在子層上的變換以及給場景內(nèi)容添加透視效果俊扳。

layer內(nèi)容

圖層是管理app內(nèi)容的數(shù)據(jù)對象森缠。圖層的內(nèi)容由包含可視數(shù)據(jù)的位圖構(gòu)成遥金。使用下述三種方式之一可給提供圖層的內(nèi)容:

  1. 直接賦值一個(gè)UIImage對象給圖層對象contents屬性缨恒。(這個(gè)技術(shù)適用于圖層內(nèi)容從不或幾乎不改變的情形恋博。)圖片類型必須是CGImageRef類型,對于Retina顯示設(shè)備吨凑,這可能也需要你去調(diào)整layer的contentsScale屬性袁勺。使用[[UIScreen mainScreen] scale]可獲取正確的縮放率儿子。
  2. 賦值一個(gè)代理給圖層郑原,由代理負(fù)責(zé)繪制圖層內(nèi)容腌紧。(該技術(shù)適用于圖層內(nèi)容可能偶爾改變茸习,且內(nèi)容可由外部對象提供,比如視圖壁肋。)
    代理方法:
@protocol CALayerDelegate <NSObject>
@optional
- (void)displayLayer:(CALayer *)layer;
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;
- (void)layerWillDraw:(CALayer *)layer
  API_AVAILABLE(macos(10.12), ios(10.0), watchos(3.0), tvos(10.0));
- (void)layoutSublayersOfLayer:(CALayer *)layer;
- (nullable id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event;
@end
// displayLayer:如果代理實(shí)現(xiàn)了這個(gè)方法号胚,那么要繪制一個(gè)bitmap,然后賦值給contents屬性
-(void)displayLayer:(CALayer *)layer
{
    NSString * imageName = @"temp";
    layer.contents = (id)[UIImage imageNamed:imageName].CGImage;
}
@end
//drawLayer:inContext:如果代理實(shí)現(xiàn)了這個(gè)方法浸遗,Core Animation提供一個(gè)context來生成bitmap猫胁,你所做的只是把想要的內(nèi)容繪制到context
-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx{
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddArc(path,NULL,100,100,95,0,M_PI*2, YES);
    CGContextBeginPath(ctx);
    CGContextAddPath(ctx,path);
    CGContextSetLineWidth(ctx, 5);
    CGContextStrokePath(ctx);
    CFRelease(path);
}
  1. 定義一個(gè)CALayer的子類并覆蓋類的繪圖方法,有覆蓋的方法返回圖層的內(nèi)容跛锌。(該技術(shù)適用于你需要?jiǎng)?chuàng)建自定義圖層的子類弃秆,或者你想改變圖層基本的繪圖行為。)
    3.1 覆蓋圖層的display方法并使用在方法中直接設(shè)置圖層的contents屬性。
    3.2 覆蓋圖層的drawInContext:方法并將需要的內(nèi)容繪制到提供的圖形上下文中菠赚。
Layer Tree圖層樹

Layer Tree分為三種脑豹,
Model Layer Tree:樹中的對象是模型對象,模型對象存儲所有動畫的目標(biāo)值衡查。無論何時(shí)改變圖層的屬性值瘩欺,你使用的始終是某一個(gè)模型對象。比如layer.position = CGPointMake(10.0,10.0)修改的就是Model Layer Tree
Presentation Tree:包含所有運(yùn)行中的動畫的瞬時(shí)值峡捡。代表顯示在屏幕上動畫的當(dāng)前值击碗。你不應(yīng)該更改這個(gè)樹中的對象。而是讀取當(dāng)前動畫的值们拙,可以創(chuàng)建開始于這些值的新的動畫稍途。
Render Tree:Render Tree中的對象執(zhí)行實(shí)際的動畫,為CoreAnimation私有的砚婆,是CoreAnimation實(shí)現(xiàn)使用的私有Tree械拍,
通過-[CALayer presentationLayer]-[CALayer modelLayer]可以訪問兩種Tree

上述三種Tree的對應(yīng)關(guān)系如下圖

image.png

常用的Layer子類
CAEmitterLayer 發(fā)射器層,用來控制粒子效果
CAGradientLayer 梯度層装盯,顏色漸變
CAEAGLLayer 用OpenGL ES繪制的層
CAReplicationLayer 用來自動復(fù)制sublayer
CAScrollLayer 用來管理可滑動的區(qū)域
CAShapeLayer 繪制立體的貝塞爾曲線
CATextLayer 可以繪制AttributeString
CATiledLayer 用來管理一副可以被分割的大圖
CATransformLayer 用來渲染3D layer的層次結(jié)構(gòu)

position 和 anchorPoint

anchorPoint :錨點(diǎn)(對layer動畫有很大影響)
position : 錨點(diǎn)在superLayer中的位置
視圖的center屬性和圖層的position屬性指定了anchorPoint相對父圖層的位置坷虑。
默認(rèn)anchorPoint值是(0.5,0.5)埂奈,位于圖層的中點(diǎn)迄损,圖層以這個(gè)點(diǎn)為中心放置,

當(dāng)改變frame時(shí),position(center)會改變账磺。
當(dāng)改變position(center)時(shí)芹敌,frame會改變。

當(dāng)改變frame時(shí)垮抗,archorPoint不變氏捞。
當(dāng)改變archorPoint時(shí),frame隨之改變

[self.tmpView setFrame:CGRectMake(50, 60, 70, 80)];
/*
frame:{{50, 60}, {70, 80}},center:{85, 100},position:{85, 100},anchorPoint:{0.5, 0.5}
*/
self.tmpView.layer.anchorPoint = CGPointMake(0, 0);
/*
frame:{{85, 100}, {70, 80}},center:{85, 100},position:{85, 100},anchorPoint:{0, 0}
*/

當(dāng)圖層做旋轉(zhuǎn)操作時(shí)冒版,會圍繞著anchorPoint對應(yīng)的點(diǎn)旋轉(zhuǎn),并且任何你對圖層陰影的變換操作也是相對于anchorPoint液茎。

frame

frame是一個(gè)派生屬性,根據(jù)layer的bounds辞嗡,position(center)捆等,archorPoint,transform計(jì)算.
當(dāng)改變bounds续室,position(center)栋烤,archorPoint,transform當(dāng)中的任何一個(gè)值時(shí)猎贴,frame都會發(fā)生變化。
當(dāng)變換后的frame是一個(gè)平行四邊形或者不平行與邊軸時(shí),返回一個(gè)最小的包括變換后的frame的四個(gè)頂點(diǎn)的矩形她渴,這個(gè)矩形就是frame达址。
當(dāng)改變frame時(shí),archorPoint趁耗,transform不變沉唠,bounds和position(center)隨之改變。

bounds

通過get和set方法苛败,直接讀取layer的bounds屬性满葛。
當(dāng)改變frame的size時(shí),bounds會改變罢屈。
當(dāng)改變bounds的size時(shí)嘀韧,frame隨之改變
修改bounds.x/y不會影響該View在父View中的位置,但是會影響該View子View的位置
比如如果設(shè)置為-20,-20缠捌,則使得坐標(biāo)系的(0锄贷,0)原點(diǎn)相對于原來向左下偏移20個(gè)單位

view的transform

view的transform屬性是直接調(diào)用的layer的affineTransform屬性的get和set方法。affineTransform實(shí)際上是一個(gè)計(jì)算屬性曼月,當(dāng)layer調(diào)用affineTransform的set方法時(shí)谊却,實(shí)際上是換算為CATransform3D類型的結(jié)構(gòu)體賦值給layer的transform屬性。
同理調(diào)用affineTransform的get方法時(shí)哑芹,也是通過layer的transform屬性換算為 CGAffineTransform返回的炎辨。
view的transform屬性等同于layer的affineTransform屬性,是通過get和set方法取的layer的transform的值聪姿。

當(dāng)改變frame時(shí)碴萧,transform不變。
當(dāng)改變transform時(shí)咳燕,frame隨之改變

Core Animation 核心動畫

Core Animation是iOS平臺上負(fù)責(zé)圖形渲染與動畫的基礎(chǔ)設(shè)施勿决。只需配置少量的動畫參數(shù)(如開始點(diǎn)位置和結(jié)束點(diǎn)的位置)即可施展Core Animation魔法。Core Animation將大部分繪圖任務(wù)交給了圖形硬件招盲,圖形硬件會加速圖形渲染的速度低缩。這種自動化的圖形加速技術(shù)讓動畫擁有更高的幀率并且更加的平滑,而且不會加重CPU的負(fù)擔(dān)曹货。
如下圖所示咆繁,Core Animation位于AppKit和UIKit的底層。Core Animation保留了部分用于擴(kuò)展其功能的的接口暴露給了應(yīng)用的視圖顶籽。使用這些接口能更細(xì)粒度地控制應(yīng)用中的動畫玩般。


image.png

Core Animation自身并不是一個(gè)繪圖系統(tǒng)。它只是一個(gè)負(fù)責(zé)在硬件上合成和操縱應(yīng)用內(nèi)容的基礎(chǔ)構(gòu)件礼饱。其核心是Layer對象坏为,Layer對象用于管理和操控應(yīng)用內(nèi)容究驴。會將捕獲的內(nèi)容放到一副位圖中。
更改圖層屬性會產(chǎn)生動畫
使用Core Animation創(chuàng)建的大部分動畫都包含對圖層屬性的配置:frame匀伏、origin洒忧、size、opacity够颠、transform熙侍,backgroundColor以及其他面向可視的屬性。
基于圖層的動畫
圖層的位圖數(shù)據(jù)和狀態(tài)信息從圖層內(nèi)容的可視呈現(xiàn)中被分離履磨。舊的屬性值動畫到新的屬性值的過程中蛉抓,分離性給了Core Animation介入此過程的機(jī)會。
例如:改變position會引起Core Animation將圖層從當(dāng)前的位置移動到新的具體位置剃诅。對其他屬性做相似的改變將引起適當(dāng)?shù)膭赢嬓Ч?br>

image.png

動畫期間巷送,Core Animation使用硬件幫你完成繪畫每一幀的工作。你只需要指定動畫的開始點(diǎn)和結(jié)束點(diǎn)综苔,如若需要惩系,也可以指定自定義信息(比如動畫運(yùn)行多久)和動畫參數(shù),如果你沒有指定如筛, Core Animation會提供適當(dāng)?shù)哪J(rèn)值堡牡。

隱式動畫

Core Animation將圖層對象屬性的變化當(dāng)做是一個(gè)觸發(fā)器,用以創(chuàng)建和安排一個(gè)或多個(gè)可執(zhí)行的隱式動畫杨刨。大部分屬性的值發(fā)生了變化都將引起Core Animation為你創(chuàng)建動畫對象晤柄,動畫對象將被安排在下一次更新周期運(yùn)行。

theLayer.opacity = 0.0;

顯式動畫

可以顯式地使用動畫對象呈現(xiàn)相同的變化妖胀,創(chuàng)建一個(gè)CAAnimation的子類對象并配置該對象的動畫參數(shù)芥颈。在添加動畫到圖層之前,指定動畫屬性的鍵路徑赚抡,接著設(shè)置動畫參數(shù):動畫的開始值與結(jié)束值爬坑,改變持續(xù)時(shí)間,或任何其他動畫參數(shù)涂臣。為了執(zhí)行一個(gè)動畫盾计,你使用addAnimation:forKey:方法將動畫對象添加到你想要展現(xiàn)動畫的圖層上。

CABasicAnimation* fadeAnimation = [CABasicAnimation animationWithKeyPath:@”opacity”;
fadeAnimation.fromValue = [NSNumber numberWithFloat:1.0];
fadeAnimation.toValue = [NSNumber numberWithFloat:0.0];
fadeAnimation.duration = 1.0;
[theLayer addAnimation:fadeAnimation forKey:nil];
//改變圖層實(shí)際的最后數(shù)據(jù)值
theLayer.opacity = 0.0;  // 記得更新圖層樹

不同于隱式動畫赁遗,隱式動畫會更新圖層對象的值署辉。而顯示動畫不會更改圖層樹中的數(shù)據(jù)。顯示動畫僅是創(chuàng)建了一個(gè)動畫岩四。如果想讓顯示動畫的改變成為永久性的哭尝,必須更新圖層屬性。

CAAnimation

CAAnimation是所有動畫對象的父類剖煌,實(shí)現(xiàn)CAMediaTiming協(xié)議,是一個(gè)抽象類材鹦,不能直接使用逝淹。

CAMediaTiming:負(fù)責(zé)控制動畫的時(shí)間、速度和時(shí)間曲線等等创橄,
/*
如果animation在animation group中,則beginTime就是其parent object——animation group 開始的一個(gè)偏移莽红。eg: beginTime為5,則在group aniamtion開始之后的5s開始動畫邦邦。
如果animation直接添加在layer(layer也遵守CAMediaTiming協(xié)議)beginTime同樣是parent object——layer 開始的一個(gè)偏移安吁,但layer的beginTime是一個(gè)過去的時(shí)間(可能是其被添加到layer tree的時(shí)間),不能簡單設(shè)置beginTime為5,去延遲動畫5s燃辖,有可能layer的beginTime加上5s也是過去的時(shí)間鬼店,當(dāng)延遲一個(gè)添加到layer上的動畫的時(shí)候,需要獲得layer的時(shí)間 `animation.beginTime  = [layer convertTime:CACurrentMediaTime() fromLayer:nil] + delay;`
*/
@property CFTimeInterval beginTime; 
@property CFTimeInterval duration; // 動畫時(shí)間
@property float speed; // 速度黔龟,如果一個(gè)動畫A :duration為1秒妇智,speed為1;而另一個(gè)動畫B:duration為2秒氏身,speed為2巍棱。則兩個(gè)動畫的時(shí)間是相同的。不過前提是它們的super layer相同蛋欣。

/* 活動本地時(shí)間的其他偏移量航徙。 從父時(shí)間tp轉(zhuǎn)換為活動本地時(shí)間t:t =(tp-開始)*speed+timeOffset。 一種用法是通過將“speed”設(shè)置為零并將“timeOffset”設(shè)置為合適的值來“暫拖莼ⅲ”動畫到踏。 */
@property CFTimeInterval timeOffset;
@property float repeatCount; // 重復(fù)count
@property CFTimeInterval repeatDuration; 
@property BOOL autoreverses; // 如果為true,則對象在向前播放后向后播放尚猿。 

/* 
kCAFillModeRemoved 是默認(rèn)值窝稿,也就是說當(dāng)動畫開始前和動畫結(jié)束后,動畫對layer都沒有影響凿掂,動畫結(jié)束后伴榔,layer會恢復(fù)到之前的狀態(tài)
kCAFillModeForwards 當(dāng)動畫結(jié)束后,layer會一直保持著動畫最后的狀態(tài)
kCAFillModeBackwards 在動畫開始前缠劝,只需要將動畫加入了一個(gè)layer潮梯,layer便立即進(jìn)入動畫的初始狀態(tài)并等待動畫開始。
kCAFillModeBoth 這個(gè)其實(shí)就是上面兩個(gè)的合成.動畫加入后開始之前惨恭,layer便處于動畫初始狀態(tài)秉馏,動畫結(jié)束后layer保持動畫最后的狀態(tài)
*/
@property(copy) CAMediaTimingFillMode fillMode;
CAAnimation提供的屬性和方法
/*
速度控制函數(shù)(CAMediaTimingFunction)
kCAMediaTimingFunctionLinear(線性):勻速,給你一個(gè)相對靜態(tài)的感覺
kCAMediaTimingFunctionEaseIn(漸進(jìn)):動畫緩慢進(jìn)入脱羡,然后加速離開
kCAMediaTimingFunctionEaseOut(漸出):動畫全速進(jìn)入萝究,然后減速的到達(dá)目的地
kCAMediaTimingFunctionEaseInEaseOut(漸進(jìn)漸出):動畫緩慢的進(jìn)入免都,中間加速,然后減速的到達(dá)目的地帆竹。這個(gè)是默認(rèn)的動畫行為绕娘。
*/
@property(nullable, strong) CAMediaTimingFunction *timingFunction;
@property(nullable, strong) id <CAAnimationDelegate> delegate;
//默認(rèn)為YES,代表動畫執(zhí)行完畢后就從圖層上移除栽连,圖形會恢復(fù)到動畫執(zhí)行前的狀態(tài)险领。如果想讓圖層保持顯示動畫執(zhí)行后的狀態(tài),那就設(shè)置為NO秒紧,不過還要設(shè)置fillMode為kCAFillModeForwards
@property(getter=isRemovedOnCompletion) BOOL removedOnCompletion;

@protocol CAAnimationDelegate <NSObject>
@optional
// 動畫已經(jīng)開始
- (void)animationDidStart:(CAAnimation *)anim;

// 當(dāng)動畫結(jié)束或從即圖層中移除時(shí)調(diào)用绢陌。 如果有效持續(xù)時(shí)間結(jié)束時(shí)沒有被刪除,則“ flag”為true熔恢。
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
@end
CAAnimation子類對象的結(jié)構(gòu)

CAPropertyAnimation

是CAAnimation的子類脐湾,也是個(gè)抽象類,要想創(chuàng)建動畫對象叙淌,應(yīng)該使用它的子類.

/* 創(chuàng)建一個(gè)新的動畫對象秤掌,其“ keyPath”屬性設(shè)置為“ path”。*/
+ (instancetype)animationWithKeyPath:(nullable NSString *)path;
/*
描述要設(shè)置動畫的屬性鹰霍。
通過指定CALayer的一個(gè)屬性名稱為keyPath,并且對這個(gè)屬性值修改闻鉴,達(dá)到相應(yīng)的動畫效果
*/
@property(nullable, copy) NSString *keyPath;
//該屬性指定該屬性動畫是否以當(dāng)前動畫效果為基礎(chǔ)。
@property(getter=isAdditive) BOOL additive;

//該屬性指定動畫是否為累加效果茂洒。
@property(getter=isCumulative) BOOL cumulative;

//該屬性值是一個(gè)CAValueFunction對象椒拗,該對象負(fù)責(zé)對屬性改變的插值計(jì)算,系統(tǒng)已經(jīng)提供了默認(rèn)的插值計(jì)算方式获黔,因此一般無須指定該屬性蚀苛。
@property(nullable, strong) CAValueFunction *valueFunction;

CABasicAnimation

/ *定義要插值的屬性值的對象。
  *所有都是可選的玷氏,并且最多不能為兩個(gè)堵未。 對象類型應(yīng)與要設(shè)置動畫的屬性的類型匹配(使用CALayer.h中描述的標(biāo)準(zhǔn)規(guī)則)。 支持的動畫模式為:
  *
  *-“ fromValue”和“ toValue”均為非零盏触。 在“ fromValue”和“ toValue”之間插值渗蟹。
  *-`fromValue'和`byValue'非零。 在'fromValue'和'fromValue'加上`byValue'之間進(jìn)行插值赞辩。
  *-“ byValue”和“ toValue”非零雌芽。 在“ toValue”減去“ byValue”和“ toValue”之間進(jìn)行插值俄认。
  *-`fromValue'非零曙博。 在`fromValue'和屬性的當(dāng)前表示值之間進(jìn)行插值。
  *-“ toValue”非零昌犹。 在渲染樹中圖層的當(dāng)前屬性值和“ toValue”之間進(jìn)行插值糟需。
  *-`byValue'非零屉佳。 在渲染樹中該圖層的當(dāng)前屬性值與加“ byValue”的值之間進(jìn)行插值谷朝。 * /
@property(nullable, strong) id fromValue; // 開始插值的值。
@property(nullable, strong) id toValue;// 結(jié)束插值的值武花。
@property(nullable, strong) id byValue; // 相對插值的值圆凰。

CAKeyframeAnimation

//表示動畫執(zhí)行的各個(gè)值(各個(gè)動作)
@property(nullable, copy) NSArray *values;
/*
基于CGPoint的屬性要遵循的路徑(比如圖層的anchorPoint屬性和position屬性)
。當(dāng)為非nil的時(shí)候覆蓋“values”屬性体箕,它默認(rèn)為nil专钉。表示以恒定的速度沿著路徑進(jìn)行動畫,
動畫沿路徑進(jìn)行的方式取決于CalculationMode屬性中的值
*/
@property(nullable) CGPathRef path;

/* 定義動畫執(zhí)行過程中每個(gè)值速度累铅,與values這個(gè)屬性中的值對應(yīng)驶沼。每個(gè)值是浮點(diǎn)數(shù)且區(qū)間為[0,1],該屬性只在calculationMode屬性被設(shè)置為kCAAnimationLinear争群,kCAAnimaitonDiscrete,kCAAnimationCubic時(shí)被使用*/
@property(nullable, copy) NSArray<NSNumber *> *keyTimes;

/*CAMediaTimingFunction(CAAnimation類中有此屬性)數(shù)組大年,如果定義了n個(gè)關(guān)鍵幀换薄,則就有n-1個(gè)CAMediaTimingFunction對象,描述的是關(guān)鍵幀到幀的節(jié)奏(速度)(該屬性替換了繼承的**timingFunction**屬性)翔试。
 */

@property(nullable, copy) NSArray<CAMediaTimingFunction *> *timingFunctions;

/* 
l calculationMode屬性定義了計(jì)算動畫定時(shí)的算法轻要。該屬性值會影響其他與定時(shí)相關(guān)屬性的使用方式。
l 線性和曲線動畫垦缅,設(shè)置為
kCAAnimationLinear:(默認(rèn)值,表示當(dāng)關(guān)鍵幀為座標(biāo)點(diǎn)的時(shí)候,關(guān)鍵幀之間直接直線相連進(jìn)行插值計(jì)算;)
CAAnimationCubic:(對關(guān)鍵幀為座標(biāo)點(diǎn)的關(guān)鍵幀進(jìn)行圓滑曲線相連后插值計(jì)算,對于曲線的形狀還可以通過tensionValues,continuityValues,biasValues來進(jìn)行調(diào)整,這里的主要目的是使得運(yùn)行的軌跡變得圓滑;)
冲泥,屬性值被用于提供定時(shí)器信息以生成動畫。這些模式值讓你最大化控制動畫的定時(shí)器壁涎。

l 節(jié)奏動畫凡恍,設(shè)置為
kCAAnimationPaced:(使得動畫均勻進(jìn)行,而不是按keyTimes設(shè)置的或者按關(guān)鍵幀平分時(shí)間,此時(shí)keyTimes和timingFunctions無效)
kCAAnimationCubicPaced:(在kCAAnimationCubic的基礎(chǔ)上使得動畫運(yùn)行變得均勻,就是系統(tǒng)時(shí)間內(nèi)運(yùn)動的距離相同,此時(shí)keyTimes以及timingFunctions也是無效的.)
這些屬性值不依賴由keyTimes或timingFunctions屬性提供的額外定時(shí)器值。相反怔球,定時(shí)器值被隱式地計(jì)算以提供一個(gè)常速率動畫嚼酝。

l 離散動畫,動畫的calculationMode屬性被設(shè)置為kCAAnimationDiscrete(離散的,就是不進(jìn)行插值計(jì)算,所有關(guān)鍵幀直接逐個(gè)進(jìn)行顯示;)竟坛,該值將引起動畫屬性從一個(gè)關(guān)鍵幀跳到另一個(gè)沒有任何補(bǔ)間動畫的下一個(gè)關(guān)鍵幀闽巩。計(jì)算模式使用keyTimes屬性值,但忽略**timingFunctions**屬性担汤。
*/
@property(copy) CAAnimationCalculationMode calculationMode;
// 動畫的張力涎跨,此屬性僅用于Cubic模式。正值表示較緊的曲線崭歧,而負(fù)值表示較圓的曲線隅很。第一個(gè)值定義了第一個(gè)控制點(diǎn)的切線的行為,第二個(gè)值控制了第二個(gè)點(diǎn)的切線率碾,依此類推外构。 如果未為給定的控制點(diǎn)指定值普泡,則使用值0。
@property(nullable, copy) NSArray<NSNumber *> *tensionValues;
/*
動畫的連續(xù)性值,此屬性僅用于Cubic模式审编。正值會導(dǎo)致尖銳的角撼班,而負(fù)值會導(dǎo)致倒角。 第一個(gè)值定義了第一個(gè)控制點(diǎn)的切線的行為垒酬,第二個(gè)值控制了第二個(gè)點(diǎn)的切線砰嘁,依此類推。 如果未為給定的控制點(diǎn)指定值勘究,則使用值0矮湘。
*/
@property(nullable, copy) NSArray<NSNumber *> *continuityValues;
/*
動畫的偏斜率,此屬性僅用于Cubic模式。 正值將曲線移到控制點(diǎn)之前口糕,而負(fù)值將曲線移到控制點(diǎn)之后缅阳。 第一個(gè)值定義了第一個(gè)控制點(diǎn)的切線的行為,第二個(gè)值控制了第二個(gè)點(diǎn)的切線景描,依此類推十办。 如果未為給定的控制點(diǎn)指定值,則使用值0超棺。
*/
@property(nullable, copy) NSArray<NSNumber *> *biasValues;


/*
設(shè)置path的動畫的對象是否旋轉(zhuǎn)以匹配路徑切線向族。它有兩個(gè)值kCAAnimationRotateAuto(自動旋轉(zhuǎn))kCAAnimationRotateAutoReverse(自動倒轉(zhuǎn))此屬性的默認(rèn)值為nil,它指示對象不應(yīng)旋轉(zhuǎn)以遵循路徑棠绘。
未提供path對象時(shí)件相,將此屬性設(shè)置為非nil值的效果是不確定的。
*/
@property(nullable, copy) CAAnimationRotationMode rotationMode;

CASpringAnimation 彈簧動畫

//質(zhì)量氧苍,影響圖層運(yùn)動時(shí)的彈簧慣性夜矗,質(zhì)量越大,彈簧拉伸和壓縮的幅度越大让虐。默認(rèn)為1侯养,且設(shè)置的時(shí)候必須大于0
@property CGFloat mass;

//剛度系數(shù)(勁度系數(shù)/彈性系數(shù)),剛度系數(shù)越大澄干,形變產(chǎn)生的力就越大逛揩,運(yùn)動越快。默認(rèn)為100麸俘,且設(shè)置的時(shí)候必須大于0
@property CGFloat stiffness;

//阻尼系數(shù)辩稽,阻止彈簧伸縮的系數(shù),阻尼系數(shù)越大从媚,停止越快逞泄,默認(rèn)為10,且設(shè)置的時(shí)候必須大于等于0
@property CGFloat damping;

//初始速率,動畫視圖的初始速度大小速率為正數(shù)時(shí)喷众,速度方向與運(yùn)動方向一致各谚,速率為負(fù)數(shù)時(shí),速度方向與運(yùn)動方向相反到千。默認(rèn)為0
@property CGFloat initialVelocity;

//結(jié)算時(shí)間昌渤,返回彈簧動畫到停止時(shí)的估算時(shí)間,根據(jù)當(dāng)前的動畫參數(shù)估算憔四,通常彈簧動畫的時(shí)間使用結(jié)算時(shí)間比較準(zhǔn)確
@property(readonly) CFTimeInterval settlingDuration;

CATransition

/*表示其漸變的效果的類型膀息。有4種分別為
kCATransitionFade(消退)kCATransitionMoveIn(漸入)kCATransitionPush(推動)kCATransitionReveal(揭開)等不同的效果
Defaults to `fade'. */
@property(copy) CATransitionType type;
//此類用于過渡運(yùn)動方向的轉(zhuǎn)變且分為上下左右四種:
//kCATransitionFromRight、kCATransitionFromLeft了赵、kCATransitionFromTop潜支、kCATransitionFromBottom
@property(nullable, copy) CATransitionSubtype subtype;
// 表示漸變開始的數(shù)值且其大小區(qū)間為[0,1],注意它必須小于或等于endProgress
// 例如,要在過渡進(jìn)行到一半時(shí)開始過渡柿汛,請將startProgress設(shè)置為0.5冗酿。
@property float startProgress;
//該值必須大于或等于startProgress,并且不大于1.0络断。 如果endProgress小于startProgress裁替,則行為未定義。 默認(rèn)值為1.0妓羊。
@property float endProgress;

CAAnimationGroup

@property(nullable, copy) NSArray<CAAnimation *> *animations;

同時(shí)進(jìn)行多個(gè)動畫。
如果你想同時(shí)給一個(gè)圖層對象應(yīng)用多個(gè)動畫稍计,你可以使用CAAnimationGroup對象將這些動畫放在一個(gè)組里躁绸。通過使用單獨(dú)的配置點(diǎn),使用組對象簡化了對多個(gè)動畫對象的管理臣嚣。應(yīng)用于動畫組的定時(shí)器和持續(xù)值將使用相同的值覆蓋單個(gè)動畫對象净刮。

CATransaction

對于分組動畫的更高級的方式是使用一個(gè)事務(wù)對象。事務(wù)提供了更加靈活的方式硅则,允許你創(chuàng)建內(nèi)嵌的動畫集合以及給每一個(gè)動畫賦值不同的動畫參數(shù)淹父。

對圖層屬性的每次更改都是事務(wù)的一部分。CATransaction類管理動畫的創(chuàng)建和分組并在適當(dāng)?shù)臅r(shí)間執(zhí)行動畫怎虫。在大部分情況下暑认,不需要?jiǎng)?chuàng)建事務(wù)。無論什么時(shí)候大审,給圖層添加顯式或隱式動畫蘸际,Core Animation會自動創(chuàng)建一個(gè)隱式事務(wù)。然而你也可以創(chuàng)建顯式事務(wù)以能夠更精確的管理動畫徒扶。

+ (void)begin; // 開始事務(wù)
+ (void)commit; // 提交事務(wù)

// 提交任何現(xiàn)存的隱式事務(wù)粮彤。
// 因?yàn)殡[式事務(wù)在runloop即將休眠時(shí)自動 flush 提交,如果沒有runloop,則此方法手動調(diào)用
//應(yīng)該避免顯式調(diào)用flush导坟。 通過runloop調(diào)用屿良,程序獲得更好的性能,原子性得保留惫周,并且事務(wù)之間進(jìn)行事務(wù)處理的事務(wù)和動畫將繼續(xù)起作用尘惧。
/* 
    使用場景
    self.view.backgroundColor = [UIColor blueColor];
    [CATransaction begin];
    self.view.backgroundColor = [UIColor redColor];
    [CATransaction commit];
    [CATransaction flush]
    while (YES) {}  // 模擬耗時(shí)操作
*/

+ (void)flush;

/* 鎖定和解鎖全局鎖。該鎖是遞歸自旋鎖(即不應(yīng)長時(shí)間保持)闯两。*/
+ (void)lock;
+ (void)unlock;

/*  定義添加到圖層的動畫的默認(rèn)持續(xù)時(shí)間褥伴。 默認(rèn)為1 / 4s。*/
+ (CFTimeInterval)animationDuration;
+ (void)setAnimationDuration:(CFTimeInterval)dur;

/* 
默認(rèn)值為nil漾狼,當(dāng)設(shè)置為非nil值時(shí)重慢,添加到圖層的所有動畫都將此值設(shè)置為其“ timingFunction”屬性。 
*/

+ (nullable CAMediaTimingFunction *)animationTimingFunction;
+ (void)setAnimationTimingFunction:(nullable CAMediaTimingFunction *)function;

/* 
定義是否使用圖層的-actionForKey:方法為每個(gè)圖層屬性更改查找動作(也稱為隱式動畫)逊躁。 默認(rèn)為否似踱,即啟用了隱式動畫。
*/
+ (BOOL)disableActions;
+ (void)setDisableActions:(BOOL)flag;
/*
一旦設(shè)置為非nil值稽煤,就保證此事務(wù)組隨后添加的所有動畫都已完成(或被刪除)核芽,就立即調(diào)用該塊(在主線程上)。 如果在提交當(dāng)前CATransaction之前未添加任何動畫(或?qū)⑼瓿蓧K設(shè)置為其他值)酵熙,則將立即調(diào)用該塊轧简。 
*/
+ (nullable void (^)(void))completionBlock;
+ (void)setCompletionBlock:(nullable void (^)(void))block;
#endif

/* 
將任意鍵控?cái)?shù)據(jù)與當(dāng)前事務(wù)關(guān)聯(lián)(即與當(dāng)前線程關(guān)聯(lián))
 讀取鍵會搜索已設(shè)置它的最內(nèi)作用域,設(shè)置鍵始終會將它設(shè)置在最內(nèi)作用域匾二。
當(dāng)前支持的事務(wù)屬性包括:“ animationDuration”哮独,“ animationTimingFunction”,“ completionBlock”察藐,“ disableActions”皮璧。
*/
+ (nullable id)valueForKey:(NSString *)key;
+ (void)setValue:(nullable id)anObject forKey:(NSString *)key;

在你想提供不同默認(rèn)值給不同的動畫集合的情況下你可以內(nèi)嵌事務(wù)。但是嵌套在內(nèi)層的事務(wù)不會立即commit分飞,會在最外層的事務(wù)結(jié)束后統(tǒng)一commit悴务。

動畫的停止

動畫通常直到運(yùn)行結(jié)束才會停止,但是你也可以根據(jù)需要提前停止動畫:

  1. 調(diào)用圖層的removeAnimationForKey:方法移除你的動畫對象譬猫。該方法使用的鍵要與調(diào)用addAnimation:forKey:方法傳入的鍵一致讯檐。你指定的鍵必須不為nil。
  2. 調(diào)用圖層的removeAllAnimations方法染服。會立即移除所有進(jìn)行中的動畫裂垦,并使用圖層當(dāng)前的狀態(tài)信息重繪圖層。

檢測一個(gè)動畫的結(jié)束

Core Animaiton提供對動畫開始與結(jié)束的檢測支持肌索。這些通知是執(zhí)行所有與動畫相關(guān)的內(nèi)務(wù)處理的最佳時(shí)刻蕉拢。比如說你可能使用開始通知設(shè)置一些相關(guān)狀態(tài)信息特碳,使用對應(yīng)的結(jié)束通知清理這些狀態(tài)。

有兩種不同的方式獲取關(guān)于動畫狀態(tài)的通知:

  1. 使用setCompletionBlock:方法添加一個(gè)完成塊給當(dāng)前的事務(wù)晕换。當(dāng)事務(wù)中的所有動畫完成后午乓,事務(wù)將執(zhí)行你的完成塊。

  2. 給CAAnimaiton對象賦值一個(gè)代理闸准,該代理實(shí)現(xiàn)了animationDidStart:方法和animaitonDidStop:finished:代理方法益愈。

如果想將兩個(gè)動畫鏈接在一起,當(dāng)?shù)谝粋€(gè)動畫結(jié)束之后啟動第二個(gè)動畫夷家。不要使用動畫通知蒸其。
使用動畫對象的beginTime屬性在某個(gè)時(shí)間啟動動畫。設(shè)置第二個(gè)動畫的開始時(shí)間為第一個(gè)動畫的結(jié)束時(shí)間库快。

UIView動畫

因?yàn)閕OS UIView總有一個(gè)Layer摸袁,UIView類從Layer對象派生了大部分的數(shù)據(jù)。因此义屏,對layer屬性的更改會通過view對象表現(xiàn)出來靠汁。因此也可以使用UIVIew接口完成對圖層屬性的更改。

如果想使用Core Animation初始化動畫闽铐,你必須在一個(gè)基于視圖的動畫塊內(nèi)部執(zhí)行所有Core Animaiton調(diào)用蝶怔。
UIView類默認(rèn)是關(guān)閉圖層動畫的,在動畫塊之外所做的改變都不是動畫兄墅,但是你可在動畫塊中重新啟用圖層動畫踢星。下面的代碼,兩個(gè)動畫都開始于相同的時(shí)間隙咸,但透明度動畫使用默認(rèn)的定時(shí)沐悦,而位置動畫使用動畫對象指定的定時(shí)。

[UIView animateWithDuration:1.0 animations:^{
myView.layer.opacity = 0.0;
CABasicAnimation* theAnim=[CABasicAnimation animationWithKeyPath:@"position"];
theAnim.fromValue = [NSValue valueWithCGPoint:myView.layer.position];
theAnim.toValue = [NSValue valueWithCGPoint:myNewPosition];
theAnim.duration = 3.0;
[myView.layer addAnimation:theAnim forKey:@"AnimateFrame"];
}];

動畫的定時(shí)

時(shí)間系統(tǒng)是動畫的一個(gè)重要部分扎瓶。通過Core Animation方法和CAMediaTiming協(xié)議可為動畫指定精確的時(shí)間信息所踊。共有兩個(gè)Core Animation類適配該協(xié)議泌枪。
其一是CAAnimation類概荷,所以你可以在動畫對象中指定時(shí)間信息。
其二是CALayer碌燕,你可以為隱式動畫配置一些與時(shí)間相關(guān)的功能误证。雖然隱式事務(wù)對象包裝了這些動畫,通常優(yōu)先使用所提供的默認(rèn)時(shí)間信息修壕。

當(dāng)考慮時(shí)間與動畫的時(shí)候愈捅,理解圖層對象如何與時(shí)間工作是重要的。每一個(gè)圖層都有自己用于管理動畫定時(shí)的本地時(shí)間系統(tǒng)慈鸠。
一般兩個(gè)不同圖層的本地時(shí)間系統(tǒng)足夠的接近蓝谨,也可以為每一個(gè)圖層指定相同的時(shí)間值。
圖層的本地時(shí)間可以被父圖層或自己的定時(shí)參數(shù)更改。比如說譬巫,改變圖層的speed屬性將引起圖層或子圖層上動畫的持續(xù)時(shí)間成比例的變化咖楣。

為了確定一個(gè)圖層的適當(dāng)時(shí)間值,CALayer類定義了convertTime:fromLayer:以及convertTime:toLayer:方法芦昔。你可以使用這些方法轉(zhuǎn)化一個(gè)固定的時(shí)間值到一個(gè)圖層的本地時(shí)間系統(tǒng)诱贿,或者將某一圖層的時(shí)間值轉(zhuǎn)換為另一個(gè)圖層的時(shí)間值。

// CACurrentMediaTime函數(shù)是一個(gè)便利函數(shù)咕缎,返回計(jì)算機(jī)的當(dāng)前時(shí)鐘時(shí)間珠十,該方法用于獲取并轉(zhuǎn)換至圖層的本地時(shí)間。
CFTimeInterval localLayerTime = [myLayer convertTime:CACurrentMediaTime() fromLayer:nil];

一旦圖層的本地時(shí)間系統(tǒng)中有一個(gè)時(shí)間值凭豪,可以使用該值更新與事件相關(guān)的動畫對象或圖層的屬性焙蹭。使用這些定時(shí)屬性,可以完成一些有趣的動畫行為墅诡,包括:

  1. 使用beginTime屬性設(shè)置動畫的開始時(shí)間壳嚎。通常,動畫開始于下一個(gè)更新循環(huán)周期末早。你可以使用beginTime參數(shù)延遲動畫的開始幾秒鐘時(shí)間烟馅。該方式將鏈接在一起的兩個(gè)動畫設(shè)置某一個(gè)動畫的開始時(shí)間為另一個(gè)動畫的結(jié)束時(shí)間。

  2. autoreverses屬性引起一個(gè)動畫在指定的持續(xù)時(shí)間內(nèi)執(zhí)行并返回到動畫的開始值然磷。你可以將此屬性與repeatCount屬性聯(lián)合使用郑趁,讓動畫在開始與結(jié)束值之間反復(fù)來回。對自動返回動畫設(shè)置重復(fù)計(jì)數(shù)為一個(gè)整數(shù)(比如1.0)將引起動畫停止在動畫的開始值姿搜。添加一個(gè)半拍值(比如重復(fù)計(jì)數(shù)為1.5)將引起動畫停止在它的結(jié)束值寡润。

  3. 對動畫組中的動畫使用timeOffset屬性,讓動畫一開始就出現(xiàn)在以后某時(shí)刻才會出現(xiàn)的狀態(tài)舅柜。(一個(gè)持續(xù)時(shí)間為5秒的動畫梭纹。動畫將從時(shí)間0到時(shí)間5運(yùn)行。如果將timeOffset設(shè)置為2,則動畫將在時(shí)間2開始烫扼,到達(dá)時(shí)間5蜻底,然后“環(huán)繞”并在時(shí)間0到時(shí)間2運(yùn)行。)

暫停與恢復(fù)動畫

為了暫停一個(gè)動畫绍载,可以利用CAMediaTiming協(xié)議,設(shè)置圖層動畫的速度為0.0.設(shè)置速度為0暫停動畫直到你改變該屬性值為一個(gè)非零值滔蝉,

-(void)pauseLayer:(CALayer*)layer {

  CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime()
                                       fromLayer:nil];
  layer.speed = 0.0;
  layer.timeOffset = pausedTime;
}


-(void)resumeLayer:(CALayer*)layer {
  CFTimeInterval pausedTime = [layer timeOffset];
  layer.speed = 1.0;
  layer.timeOffset = 0.0;
  layer.beginTime = 0.0;
  CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime()
                                           fromLayer:nil] - pausedTime;
  layer.beginTime = timeSincePause;
}

改變一個(gè)圖層的默認(rèn)隱式動畫

Core Animation使用動作對象為圖層實(shí)現(xiàn)了隱式動畫行為击儡。動作對象遵守CAAction協(xié)議并定義了一些運(yùn)行于圖層的相關(guān)行為。
所有CAAnimation對象都實(shí)現(xiàn)了這個(gè)協(xié)議蝠引。

自定義動作對象

為了創(chuàng)建你自己的動作對象阳谍,你需要遵守CAAction協(xié)議并實(shí)現(xiàn)協(xié)議里唯一的方法:runActionForKey:object:arguments:方法蛀柴。在該方法中執(zhí)行在圖層上的動作。你可能使用該方法給圖層添加動畫對象或使用該方法執(zhí)行另外的任務(wù)矫夯。

當(dāng)定義了一個(gè)動作對象名扛,必須決定動作以何種方式被觸發(fā)。動作的觸發(fā)器定義了你用于注冊動作的key茧痒。動作對象可在下面的情況下被觸發(fā):

  1. 圖層的某一個(gè)屬性值被改變肮韧。這可以是圖層的任何一個(gè)屬性,不僅僅是可動畫的屬性旺订。 (你也可以給添加到圖層的自定義屬性關(guān)聯(lián)動作弄企。)識別動作的鍵是屬性名。

  2. 圖層變成可視或被加入到圖層層次中区拳。則識別動作的鍵為kCAOnOrderIn拘领。

  3. 圖層從圖層層次中被移除。則識別動作的鍵為kCAOnOrderOut樱调。

  4. 圖層是即將包含一個(gè)變換動畫约素。則識別動作的鍵為kCATransition。

@interface CustomAction : NSObject<CAAction>
@property (nonatomic) CGColorRef currentColor;
@end
@implementation CustomAction
- (void)runActionForKey:(NSString *)key object:(id)anObject arguments:(NSDictionary *)dict {
    CustomLayer *layer = anObject;
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
    animation.fromValue = (id)[UIColor greenColor].CGColor;
    animation.toValue = (id)[UIColor redColor].CGColor;
    animation.duration = 5;
    [layer addAnimation:animation forKey:@"backgroundColor"];
}
@end

動作對象設(shè)置給圖層才產(chǎn)生效果

在動作被執(zhí)行之前笆凌,圖層需要找到相應(yīng)的動作對象圣猎。相關(guān)的動作的鍵可以是被更改的屬性名或一個(gè)特殊的識別動作的字符串。
當(dāng)事件發(fā)生在圖層上乞而,圖層調(diào)用它的actionForKey:方法搜索與鍵關(guān)聯(lián)的動作對象送悔。我們可以介入,并提供一個(gè)與鍵相關(guān)的動作對象爪模。
Core Animation以下面的順序搜索動作對象:

  1. 如果圖層有一個(gè)代理欠啤,并且代理實(shí)現(xiàn)了actionForLayer:forKey:方法,圖層調(diào)用該方法屋灌。代理必須完成下面所述操作之一:
    l 返回給定的鍵指定的動作對象
    l 如果代理不處理動作則返回nil洁段,而搜索操作將繼續(xù)。
    l 返回NSNull對象共郭,這將引起搜索操作立即結(jié)束祠丝。CALayer不會做任何動畫;
  2. 圖層在圖層的action字典內(nèi)搜索給定的鍵
  3. 圖層在style字典中查詢一個(gè)包含鍵的動作字典落塑。(換句話說纽疟,style字典包含一個(gè)actions鍵罐韩,它的值也是字典憾赁。圖層在第二個(gè)字典中搜索給定的鍵。)
  4. 圖層調(diào)用它的defaultActionForKey:類方法散吵。 圖層執(zhí)行由Core Animation定義的隱式動作(如果有)龙考。

如果任何一個(gè)搜索點(diǎn)提供了動作對象蟆肆,圖層將停止搜索并執(zhí)行返回對象的runActionForKey:object:arguments:方法執(zhí)行動作。
如果動作是一個(gè)CAAnimation對象晦款,則把自身添加到layer上炎功,使用默認(rèn)的方法實(shí)現(xiàn)執(zhí)行動畫。如果是一個(gè)正確的實(shí)現(xiàn)了CAAction協(xié)議的對象缓溅,則CALayer用這個(gè)對象來生成一個(gè)CAAnimation蛇损,并加到自己身上進(jìn)行動畫。
CAAnimation

CALayer可動畫屬性

屬性 默認(rèn)動畫
anchorPoint 使用默認(rèn)隱式的CABasicAnimation對象坛怪,描述于Table B-2淤齐。
backgroundColor 使用默認(rèn)的隱式CABasicAnimation對象,描述于Table B-2袜匿。
backgroundFilters 使用默認(rèn)的CATransition對象更啄,描述于Table B-3。濾鏡的字屬性被動畫使用默認(rèn)隱式CABasicAnimation對象居灯,描述于Table B-2祭务。
borderColor 使用默認(rèn)隱式的CABasicAnimation對象,描述于Table B-2怪嫌。
borderWidth 使用默認(rèn)隱式的CABasicAnimation對象义锥,描述于Table B-2。
bounds 使用默認(rèn)隱式的CABasicAnimation對象岩灭,描述于Table B-2缨该。
compositingFilter 使用默認(rèn)的CATransition對象,描述于Table B-3川背。濾鏡的字屬性被動畫使用默認(rèn)隱式CABasicAnimation對象贰拿,描述于Table B-2。
contents 使用默認(rèn)隱式的CABasicAnimation對象熄云,描述于Table B-2)膨更。
contentsRect 使用默認(rèn)隱式的CABasicAnimation對象,描述于Table B-2缴允。
cornerRadius 使用默認(rèn)隱式的CABasicAnimation對象荚守,描述于Table B-2。
doubleSided 沒有默認(rèn)的隱式動畫
filters 使用默認(rèn)的CATransition對象练般,描述于Table B-3矗漾。濾鏡的字屬性被動畫使用默認(rèn)隱式CABasicAnimation對象,描述于Table B-2薄料。
frame 該屬性是不可動畫的敞贡。你可以動畫bounds和position屬性達(dá)到相同的效果。
hidden 使用默認(rèn)隱式的CABasicAnimation對象摄职,描述于Table B-2誊役。
mask 使用默認(rèn)隱式的CABasicAnimation對象获列,描述于Table B-2。
masksToBounds 使用默認(rèn)隱式的CABasicAnimation對象蛔垢,描述于Table B-2击孩。
opacity 使用默認(rèn)隱式的CABasicAnimation對象,描述于Table B-2鹏漆。
position 使用默認(rèn)隱式的CABasicAnimation對象巩梢,描述于Table B-2。
shadowColor 使用默認(rèn)隱式的CABasicAnimation對象艺玲,描述于Table B-2且改。
shadowOffset 使用默認(rèn)隱式的CABasicAnimation對象,描述于Table B-2板驳。
shadowOpacity 使用默認(rèn)隱式的CABasicAnimation對象又跛,描述于Table B-2。
shadowPath 使用默認(rèn)隱式的CABasicAnimation對象若治,描述于Table B-2慨蓝。
shadowRadius 使用默認(rèn)隱式的CABasicAnimation對象,描述于Table B-2端幼。
sublayers 使用默認(rèn)隱式的CABasicAnimation對象礼烈,描述于Table B-2。
sublayerTransform 使用默認(rèn)隱式的CABasicAnimation對象婆跑,描述于Table B-2此熬。
transform 使用默認(rèn)隱式的CABasicAnimation對象,描述于Table B-2滑进。
zPosition 使用默認(rèn)隱式的CABasicAnimation對象犀忱,描述于Table B-2。

表B-2 默認(rèn)隱式的基本動畫

描述
CABasicAnimation
持續(xù)時(shí)間 0.25秒扶关,或是當(dāng)前事務(wù)的持續(xù)時(shí)間
鍵路徑 設(shè)置圖層的屬性名

表B-3 默認(rèn)隱式過渡

描述
CATransition
持續(xù)時(shí)間 0.25秒阴汇,或當(dāng)前事務(wù)的持續(xù)時(shí)間
類型 減淡(kCATransitionFade)
開始進(jìn)度 0.0
結(jié)束進(jìn)度 1.0

CATransform3D鍵路徑

可以使用鍵路徑檢索一個(gè)CATransform3D數(shù)據(jù)類型的屬性的變換值〗诨保可使用字符串值transform或sublayerTransform搀庶,后面跟上表C-2中中的域作為鍵路徑。比如铜异,transform.rotation.z哥倔。

表C-2 變換域的鍵路徑

域的鍵路徑 描述
rotation.x 設(shè)置一個(gè)NSNumber類型的繞x方向旋轉(zhuǎn)的弧度值。
rotation.y 設(shè)置一個(gè)NSNumber類型的繞y方向旋轉(zhuǎn)的弧度值揍庄。
rotation.z 設(shè)置一個(gè)NSNumber類型的繞z方向旋轉(zhuǎn)的弧度值咆蒿。
rotation 設(shè)置一個(gè)NSNumber類型的繞z方向旋轉(zhuǎn)的弧度值。該設(shè)置和ratation.z是功能是一樣的。
scale.x 設(shè)置一個(gè)NSNumber對象蜡秽,它的值是在x軸上縮放因子。
scale.y 設(shè)置一個(gè)NSNumber對象缆镣,它的值是在y軸上縮放因子芽突。
scale.z 設(shè)置一個(gè)NSNumber對象,它的值是在z軸上縮放因子董瞻。
scale 設(shè)置一個(gè)NSNumber對象寞蚌,它的值是三個(gè)縮放因子的平均值。
translation.x 設(shè)置一個(gè)NSNumber對象钠糊,它的值是x軸方向的平移因子挟秤。
translation.y 設(shè)置一個(gè)NSNumber對象,它的值是y軸方向的平移因子抄伍。
translation.z 設(shè)置一個(gè)NSNumber對象艘刚,它的值是z軸方向的平移因子。
translation 設(shè)置一個(gè)包含NSSize或CGSize數(shù)據(jù)類型的NSValue對象截珍。該數(shù)據(jù)類型表明在x和y軸上的平移數(shù)量攀甚。
//設(shè)置x軸的平移因子為10點(diǎn),圖層將按指定的坐標(biāo)軸方向平移給定的點(diǎn)數(shù)量岗喉。
[myLayer setValue:[NSNumber numberWithFloat:10.0] forKeyPath:@”transform.translation.x”];

CGPoint鍵路徑

如果屬性的值是CGPoint數(shù)據(jù)類型秋度,你可以選擇表C-3其中的域名追加給屬性以獲得值或設(shè)置值 。
表C-3 CGPoint數(shù)據(jù)結(jié)構(gòu)

結(jié)構(gòu)域 描述
x 一個(gè)點(diǎn)的x坐標(biāo)钱床。
y 一個(gè)點(diǎn)的y坐標(biāo)荚斯。

CGSize鍵路徑

如果屬性值是一個(gè)CGSize數(shù)據(jù)類型,你可以選擇表C-4中其中一個(gè)域名追加給屬性以獲得值或設(shè)置值查牌。

表C-4 CGSize數(shù)據(jù)結(jié)構(gòu)域

結(jié)構(gòu)域 描述
width size的width屬性事期。
height size的height屬性。

CGRect鍵路徑

如果給定的屬性是CGRect數(shù)據(jù)類型值纸颜,你可以選擇表C-5中其中一個(gè)域名追加給屬性以獲取或設(shè)置值刑赶。

表C-5 CGRect數(shù)據(jù)結(jié)構(gòu)的域名

結(jié)構(gòu)體域 描述
orign 矩形的原始點(diǎn)
origin.x 矩形原始點(diǎn)的x坐標(biāo)
origin.y 矩形原始點(diǎn)的y坐標(biāo)
size 矩形的尺寸
size.width 矩形尺寸的寬度屬性
size.height 矩形尺寸的高度屬性

UIView動畫

UIView動畫是iOS開發(fā)中最廉價(jià)也是最常用的動畫。
UIView動畫能夠設(shè)置的動畫屬性有:

  • frame
  • bounds
  • center
  • transform
  • alpha
  • backgroundColor
  • contentStretch

UIView動畫使用方式

類似于事務(wù)的方式(在iOS13 廢棄了)

創(chuàng)建動畫

// 第一個(gè)參數(shù): 動畫標(biāo)識
// 第二個(gè)參數(shù): 附加參數(shù),在設(shè)置代理情況下懂衩,
//此參數(shù)將發(fā)送到setAnimationWillStartSelector和setAnimationDidStopSelector所指定的方法撞叨,
//大部分情況,設(shè)置為nil.
[UIView beginAnimations:(nullable NSString *) context:(nullable void *)];

提交動畫

[UIView commitAnimations];

相關(guān)方法

//動畫持續(xù)時(shí)間
[UIView setAnimationDuration:(NSTimeInterval)];
//動畫的代理對象 
[UIView setAnimationDelegate:(nullable id)];
//設(shè)置動畫將開始時(shí)代理對象執(zhí)行的SEL
[UIView setAnimationWillStartSelector:(nullable SEL)];
//設(shè)置動畫延遲執(zhí)行的時(shí)間
[UIView setAnimationDelay:(NSTimeInterval)];
//設(shè)置動畫的重復(fù)次數(shù)
[UIView setAnimationRepeatCount:(float)];
//設(shè)置動畫的曲線
/*
UIViewAnimationCurve的枚舉值:
UIViewAnimationCurveEaseInOut,         // 慢進(jìn)慢出(默認(rèn)值)
UIViewAnimationCurveEaseIn,            // 慢進(jìn)
UIViewAnimationCurveEaseOut,           // 慢出
UIViewAnimationCurveLinear             // 勻速
*/
[UIView setAnimationCurve:(UIViewAnimationCurve)];
//設(shè)置是否從當(dāng)前狀態(tài)開始播放動畫
/*假設(shè)上一個(gè)動畫正在播放浊洞,且尚未播放完畢牵敷,我們將要進(jìn)行一個(gè)新的動畫:
當(dāng)為YES時(shí):動畫將從上一個(gè)動畫所在的狀態(tài)開始播放
當(dāng)為NO時(shí):動畫將從上一個(gè)動畫所指定的最終狀態(tài)開始播放(此時(shí)上一個(gè)動畫馬上結(jié)束)*/
[UIView setAnimationBeginsFromCurrentState:YES];
//設(shè)置動畫是否繼續(xù)執(zhí)行相反的動畫
[UIView setAnimationRepeatAutoreverses:(BOOL)];
//是否禁用動畫效果(對象屬性依然會被改變,只是沒有動畫效果)
[UIView setAnimationsEnabled:(BOOL)];
//設(shè)置視圖的過渡效果
/* 第一個(gè)參數(shù):UIViewAnimationTransition的枚舉值如下
     UIViewAnimationTransitionNone,              //不使用動畫
     UIViewAnimationTransitionFlipFromLeft,      //從左向右旋轉(zhuǎn)翻頁
     UIViewAnimationTransitionFlipFromRight,     //從右向左旋轉(zhuǎn)翻頁
     UIViewAnimationTransitionCurlUp,            //從下往上卷曲翻頁
     UIViewAnimationTransitionCurlDown,          //從上往下卷曲翻頁
 第二個(gè)參數(shù):需要過渡效果的View
 第三個(gè)參數(shù):是否使用視圖緩存法希,YES:視圖在開始和結(jié)束時(shí)渲染一次枷餐;NO:視圖在每一幀都渲染*/
[UIView setAnimationTransition:(UIViewAnimationTransition) forView:(nonnull UIView *) cache:(BOOL)];
Block 動畫
@interface UIView(UIViewAnimation)
// 動畫是否可用
+ (void)setAnimationsEnabled:(BOOL)enabled; 
@property(class, nonatomic, readonly) BOOL areAnimationsEnabled;
// 在沒有動畫的情況下執(zhí)行block里的代碼。
+ (void)performWithoutAnimation:(void (NS_NOESCAPE ^)(void))actionsWithoutAnimation API_AVAILABLE(ios(7.0));
//當(dāng)前動畫的持續(xù)時(shí)間苫亦。?
@property(class, nonatomic, readonly) NSTimeInterval inheritedAnimationDuration API_AVAILABLE(ios(9.0));

@end

@interface UIView(UIViewAnimationWithBlocks)
/*
 UIViewAnimationOptionLayoutSubviews            //進(jìn)行動畫時(shí)布局子控件
 UIViewAnimationOptionAllowUserInteraction      //進(jìn)行動畫時(shí)允許用戶交互
 UIViewAnimationOptionBeginFromCurrentState     //從當(dāng)前狀態(tài)開始動畫
 UIViewAnimationOptionRepeat                    //無限重復(fù)執(zhí)行動畫
 UIViewAnimationOptionAutoreverse               //執(zhí)行動畫回路
 UIViewAnimationOptionOverrideInheritedDuration //忽略嵌套動畫的執(zhí)行時(shí)間設(shè)置
 UIViewAnimationOptionOverrideInheritedCurve    //忽略嵌套動畫的曲線設(shè)置
 UIViewAnimationOptionAllowAnimatedContent      //轉(zhuǎn)場:進(jìn)行動畫時(shí)重繪視圖
 UIViewAnimationOptionShowHideTransitionViews   //轉(zhuǎn)場:移除(添加和移除圖層的)動畫效果
 UIViewAnimationOptionOverrideInheritedOptions  //不繼承父動畫設(shè)置

 UIViewAnimationOptionCurveEaseInOut            //時(shí)間曲線毛肋,慢進(jìn)慢出(默認(rèn)值)
 UIViewAnimationOptionCurveEaseIn               //時(shí)間曲線怨咪,慢進(jìn)
 UIViewAnimationOptionCurveEaseOut              //時(shí)間曲線,慢出
 UIViewAnimationOptionCurveLinear               //時(shí)間曲線润匙,勻速

 UIViewAnimationOptionTransitionNone            //轉(zhuǎn)場诗眨,不使用動畫
 UIViewAnimationOptionTransitionFlipFromLeft    //轉(zhuǎn)場,從左向右旋轉(zhuǎn)翻頁
 UIViewAnimationOptionTransitionFlipFromRight   //轉(zhuǎn)場孕讳,從右向左旋轉(zhuǎn)翻頁
 UIViewAnimationOptionTransitionCurlUp          //轉(zhuǎn)場匠楚,下往上卷曲翻頁
 UIViewAnimationOptionTransitionCurlDown        //轉(zhuǎn)場,從上往下卷曲翻頁
 UIViewAnimationOptionTransitionCrossDissolve   //轉(zhuǎn)場厂财,交叉消失和出現(xiàn)
 UIViewAnimationOptionTransitionFlipFromTop     //轉(zhuǎn)場芋簿,從上向下旋轉(zhuǎn)翻頁
 UIViewAnimationOptionTransitionFlipFromBottom  //轉(zhuǎn)場,從下向上旋轉(zhuǎn)翻頁
*/
// 可以設(shè)置延時(shí)時(shí)間和過渡效果的Block動畫
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion API_AVAILABLE(ios(4.0));
// 帶有動畫提交回調(diào)的Block動畫
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion API_AVAILABLE(ios(4.0)); // delay = 0.0, options = 0

// 最簡潔的Block動畫:包含時(shí)間和動畫:
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations API_AVAILABLE(ios(4.0)); // delay = 0.0, options = 0, completion = NULL

// 彈簧動畫
// 參數(shù)依次是
//動畫持續(xù)時(shí)間
//動畫延遲執(zhí)行的時(shí)間
//震動效果璃饱,范圍0~1与斤,數(shù)值越小震動效果越明顯
//初始速度,數(shù)值越大初始速度越快
//動畫的過渡效果
//執(zhí)行的動畫
//動畫執(zhí)行提交后的操作
+ (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 API_AVAILABLE(ios(7.0));

// 轉(zhuǎn)場動畫 
// 單個(gè)視圖的過渡效果
+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))animations completion:(void (^ __nullable)(BOOL finished))completion API_AVAILABLE(ios(4.0));

/* 
toView已添加到fromView.superview荚恶,fromView已從其超級視圖中刪除注意轉(zhuǎn)場動畫的作用對象是父視圖(過渡效果體現(xiàn)在父視圖上)幽告。調(diào)用該方法相當(dāng)于執(zhí)行下面兩句代碼:
[fromView.superview addSubview:toView];
[fromView removeFromSuperview];
*/
+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^ __nullable)(BOOL finished))completion API_AVAILABLE(ios(4.0));

/* 在一個(gè)或多個(gè)視圖上執(zhí)行請求的系統(tǒng)提供的動畫。 在parallelAnimations塊中指定其他動畫裆甩。 這些附加動畫將與系統(tǒng)動畫一起運(yùn)行冗锁,并具有與系統(tǒng)動畫定義/繼承相同的時(shí)間和持續(xù)時(shí)間。 其他動畫不應(yīng)修改在其上執(zhí)行系統(tǒng)動畫的視圖的屬性嗤栓。 并非所有的系統(tǒng)動畫支持所有的options冻河。
 */
+ (void)performSystemAnimation:(UISystemAnimation)animation onViews:(NSArray<__kindof UIView *> *)views options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))parallelAnimations completion:(void (^ __nullable)(BOOL finished))completion API_AVAILABLE(ios(7.0));

/* 
從動畫塊中調(diào)用此方法以重復(fù)動畫,否則無效茉帅。 重復(fù)動畫的總持續(xù)時(shí)間可以通過(outerAnimationDuration * repeatCount * autoreverses叨叙?2:1)計(jì)算。
 */
+ (void)modifyAnimationsWithRepeatCount:(CGFloat)count autoreverses:(BOOL)autoreverses animations:(void(NS_NOESCAPE ^)(void))animations API_AVAILABLE(ios(12.0),tvos(12.0));

@end

@interface UIView (UIViewKeyframeAnimations)
/*
UIViewAnimationOptionLayoutSubviews           //進(jìn)行動畫時(shí)布局子控件
UIViewAnimationOptionAllowUserInteraction     //進(jìn)行動畫時(shí)允許用戶交互
UIViewAnimationOptionBeginFromCurrentState    //從當(dāng)前狀態(tài)開始動畫
UIViewAnimationOptionRepeat                   //無限重復(fù)執(zhí)行動畫
UIViewAnimationOptionAutoreverse              //執(zhí)行動畫回路
UIViewAnimationOptionOverrideInheritedDuration //忽略嵌套動畫的執(zhí)行時(shí)間設(shè)置
UIViewAnimationOptionOverrideInheritedOptions //不繼承父動畫設(shè)置

UIViewKeyframeAnimationOptionCalculationModeLinear     //運(yùn)算模式 :連續(xù)
UIViewKeyframeAnimationOptionCalculationModeDiscrete   //運(yùn)算模式 :離散
UIViewKeyframeAnimationOptionCalculationModePaced      //運(yùn)算模式 :均勻執(zhí)行
UIViewKeyframeAnimationOptionCalculationModeCubic      //運(yùn)算模式 :平滑
UIViewKeyframeAnimationOptionCalculationModeCubicPaced //運(yùn)算模式 :平滑均勻
*/
// 關(guān)鍵幀動畫堪澎,支持屬性關(guān)鍵幀擂错,不支持路徑關(guān)鍵幀
+ (void)animateKeyframesWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewKeyframeAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion API_AVAILABLE(ios(7.0));
//動畫開始的時(shí)間(占總時(shí)間的比例),
// 動畫持續(xù)時(shí)間(占總時(shí)間的比例)
+ (void)addKeyframeWithRelativeStartTime:(double)frameStartTime relativeDuration:(double)frameDuration animations:(void (^)(void))animations API_AVAILABLE(ios(7.0)); // start time and duration are values between 0.0 and 1.0 specifying time and duration relative to the overall time of the keyframe animation

@end

UIView 動畫原理

之前已經(jīng)介紹過,隱式動畫的執(zhí)行過程樱蛤,是通過找到一個(gè) 實(shí)現(xiàn)了 CAAction協(xié)議的類對象钮呀,調(diào)用協(xié)議方法實(shí)現(xiàn)的。
當(dāng)直接修改View的屬性昨凡,也會反饋到layer上爽醋,但并沒有動畫,是因?yàn)楸慵梗瑅iew是layer的代理蚂四,返回了NSNull對象,不會產(chǎn)生動畫
當(dāng)使用UIView提供的api進(jìn)行動畫時(shí),會返回一個(gè)Action對象遂赠,然后該對象添加了動畫久妆。

/** UIView 動畫產(chǎn)生原理 */
- (void)uiviewAnimation {
    NSLog(@"%@",[self.view.layer.delegate actionForLayer:self.view.layer forKey:@"position"]); // <null>

    [UIView animateWithDuration:1.25 animations:^{
        NSLog(@"%@",[self.view.layer.delegate actionForLayer:self.view.layer forKey:@"position"]); // <_UIViewAdditiveAnimationAction: 0x600001ff0d40>
    }];
}

UIViewController轉(zhuǎn)場動畫

簡單描述下UIViewController轉(zhuǎn)場動畫

自定義轉(zhuǎn)場動畫

在 Navigation Controller 中,實(shí)現(xiàn)一個(gè)自定義的 push 動畫效果跷睦。為了完成這個(gè)任務(wù)筷弦,需要實(shí)現(xiàn) UINavigationControllerDelegate 中的方法:

//可以根據(jù)不同的 operation(Push 或 Pop)返回不同的 animator。我們可以把 animator 存到一個(gè)屬性中送讲,從而在多個(gè) operation 之間實(shí)現(xiàn)共享奸笤,或者我們也可以為每個(gè) operation 都創(chuàng)建一個(gè)新的 animator 對象
- (id<UIViewControllerAnimatedTransitioning>)
                   navigationController:(UINavigationController *)navigationController
        animationControllerForOperation:(UINavigationControllerOperation)operation
                     fromViewController:(UIViewController*)fromVC
                       toViewController:(UIViewController*)toVC
{
    if (operation == UINavigationControllerOperationPush) {
        return self.animator;
    }
    return nil;
}

我們需要?jiǎng)?chuàng)建遵守UIViewControllerAnimatedTransitioning協(xié)議的對象惋啃。

@protocol UIViewControllerAnimatedTransitioning <NSObject>

//詢問動畫對象過渡動畫的持續(xù)時(shí)間(以秒為單位)哼鬓。
- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext;
/*
在呈現(xiàn)或關(guān)閉視圖控制器時(shí),會調(diào)用此方法边灭∫煜#可以配置與自定義過渡相關(guān)聯(lián)的動畫。您可以使用UIView動畫或“核心動畫”來配置動畫绒瘦。
所有動畫都必須在transitionContext的containerView屬性指定的視圖中進(jìn)行称簿。
將要顯示的視圖添加到容器視圖的層次結(jié)構(gòu)中,并設(shè)置您想要使該視圖移動到位的所有動畫惰帽。
如果要在沒有視圖的情況下直接繪制到屏幕憨降,請使用此方法配置CADisplayLink對象。
您可以從transitionContext的viewControllerForKey:方法檢索與轉(zhuǎn)換有關(guān)的視圖控制器该酗。
*/
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext;

@optional

//如果轉(zhuǎn)場可以被中斷授药,則實(shí)現(xiàn)此方法(例如UIViewPropertyAnimator對象)
- (id <UIViewImplicitlyAnimating>) interruptibleAnimatorForTransition:(id <UIViewControllerContextTransitioning>)transitionContext API_AVAILABLE(ios(10.0));

// 這是一種便利,如果在調(diào)用過渡上下文的completeTransition:方法時(shí)實(shí)現(xiàn)呜魄,則將由系統(tǒng)調(diào)用該實(shí)現(xiàn)悔叽。
- (void)animationEnded:(BOOL) transitionCompleted;

@end

系統(tǒng)調(diào)用上述協(xié)議的時(shí)候,參數(shù)是一個(gè)遵守UIViewControllerContextTransitioning協(xié)議的上下文對象

@protocol UIViewControllerContextTransitioning <NSObject>

// 容器視圖充當(dāng)動畫序列期間所有其他視圖(包括消失和呈現(xiàn)的視圖控制器的視圖)的父視圖爵嗅。
@property(nonatomic, readonly) UIView *containerView;
//允許自定義過渡向容器視圖添加或刪除子視圖娇澎。對于除UIModalPresentationCustom樣式以外的模態(tài)表示樣式,此屬性的值始終為YES睹晒。 
// 當(dāng)模式表示樣式為UIModalPresentationCustom時(shí)趟庄,如果過渡應(yīng)設(shè)置動畫,則值為YES伪很;否則岔激,則為NO。 
// 使用此值可以確定是否需要對自定義過渡進(jìn)行動畫處理是掰,或者是否應(yīng)在不對更改進(jìn)行動畫處理的情況下將最終視圖安裝到容器中虑鼎。
@property(nonatomic, readonly, getter=isAnimated) BOOL animated;

// 這表明過渡當(dāng)前是否是交互式的。
@property(nonatomic, readonly, getter=isInteractive) BOOL interactive; 
// 轉(zhuǎn)場是否取消
@property(nonatomic, readonly) BOOL transitionWasCancelled;
// 控制器過渡的表示樣式。
@property(nonatomic, readonly) UIModalPresentationStyle presentationStyle;

// 更新
- (void)updateInteractiveTransition:(CGFloat)percentComplete;
 // 完成
- (void)finishInteractiveTransition;
// 取消
- (void)cancelInteractiveTransition;
// 暫停
- (void)pauseInteractiveTransition API_AVAILABLE(ios(10.0));

// 每當(dāng)轉(zhuǎn)換完成(或取消轉(zhuǎn)換)時(shí)炫彩,都必須調(diào)用此方法匾七。
// 通常,此方法由符合由轉(zhuǎn)換委托售賣的UIViewControllerAnimatedTransitioning協(xié)議的對象調(diào)用江兢。 對于純交互式過渡昨忆,應(yīng)由交互控制器調(diào)用。 
- (void)completeTransition:(BOOL)didComplete;


//目前,只有兩個(gè)鍵
//-UITransitionContextToViewControllerKey,
// UITransitionContextFromViewControllerKey励幼。
//不應(yīng)操縱視圖,而應(yīng)使用viewForKey:獲取視圖性置。
- (nullable __kindof UIViewController *)viewControllerForKey:(UITransitionContextViewControllerKey)key;

//目前,系統(tǒng)僅定義了兩個(gè)鍵-
// UITransitionContextFromViewKey和UITransitionContextToViewKey
// 可能返回nil,這表明不應(yīng)該操作關(guān)聯(lián)的視圖控制器的視圖繁疤。
- (nullable __kindof UIView *)viewForKey:(UITransitionContextViewKey)key API_AVAILABLE(ios(8.0));
// 指示在過渡期間要應(yīng)用的旋轉(zhuǎn)量。
@property(nonatomic, readonly) CGAffineTransform targetTransform API_AVAILABLE(ios(8.0));

/*
此方法返回的矩形代表轉(zhuǎn)換開始時(shí)相應(yīng)視圖的大小秕狰。 對于已經(jīng)在屏幕上的視圖控制器稠腊,此矩形通常與容器視圖的框架矩形匹配。 對于即將顯示的視圖控制器鸣哀,此方法返回的值通常為CGRectZero架忌,因?yàn)橐晥D尚未顯示在屏幕上。
*/
- (CGRect)initialFrameForViewController:(UIViewController *)vc;
/*
此方法返回的矩形表示轉(zhuǎn)換結(jié)束時(shí)相應(yīng)視圖的大小我衬。 對于演示過程中涉及的視圖叹放,此方法返回的值可能是CGRectZero,但也可能是有效的框架矩形低飒。
*/
- (CGRect)finalFrameForViewController:(UIViewController *)vc;
@end

交互式的轉(zhuǎn)場動畫

想要?jiǎng)赢嬜兊乜梢越换シ浅:唵涡碜颍覀冎恍枰采w另一個(gè) UINavigationControllerDelegate 的方法:

- (id <UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController*)navigationController
                          interactionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>)animationController
{
    return self.interactionController;
}

注意,在非交互式動畫效果中褥赊,該方法返回 nil糕档。
這里返回的 interaction controller 是 UIPercentDrivenInteractiveTransition 類的一個(gè)實(shí)例。
而關(guān)于UIViewControllerInteractiveTransitioning

@protocol UIViewControllerInteractiveTransitioning <NSObject>
/*
此方法的實(shí)現(xiàn)應(yīng)使用transitionContext參數(shù)中的數(shù)據(jù)為過渡配置用戶交互性拌喉,然后啟動動畫速那。 在跟蹤用戶互動時(shí),應(yīng)定期調(diào)用上下文對象的updateInteractiveTransition:方法尿背,以報(bào)告現(xiàn)在完成了多少轉(zhuǎn)換端仰。 
如果事件指示用戶已取消轉(zhuǎn)換,請調(diào)用cancelInteractiveTransition方法田藐。 如果事件指示過渡已完成荔烧,請調(diào)用finishInteractiveTransition方法吱七。
*/
- (void)startInteractiveTransition:(id <UIViewControllerContextTransitioning>)transitionContext;

@optional
// 在交互部分完成后鹤竭,系統(tǒng)需要完成交互轉(zhuǎn)換的速度時(shí)調(diào)用。
@property(nonatomic, readonly) CGFloat completionSpeed;
// 當(dāng)系統(tǒng)需要?jiǎng)赢嬐瓿汕€以進(jìn)行交互式視圖控制器轉(zhuǎn)換時(shí)調(diào)用
@property(nonatomic, readonly) UIViewAnimationCurve completionCurve;
/*
當(dāng)過渡從開始就具有交互性時(shí)稚机,此屬性的值為YES颜凯。 當(dāng)過渡以非交互方式開始時(shí),該屬性為NO募壕。 但是代嗤,即使過渡開始時(shí)是非交互的硝逢,如果它實(shí)現(xiàn)UIViewControllerAnimatedTransitioning協(xié)議的interruptibleAnimatorForTransition:方法综芥,則以后也可能變?yōu)榻换ナ健?*/
@property (nonatomic, readonly) BOOL wantsInteractiveStart API_AVAILABLE(ios(10.0));

@end

UIPercentDrivenInteractiveTransition

UIKIT_EXTERN API_AVAILABLE(ios(7.0)) @interface UIPercentDrivenInteractiveTransition : NSObject <UIViewControllerInteractiveTransitioning>

// 這是在過渡開始時(shí)調(diào)用<UIViewControllerAnimatedTransitioning>`transitionDuration:`方法時(shí)返回的非交互持續(xù)時(shí)間额各。
@property (readonly) CGFloat duration;

/// 由updateInteractiveTransition指定的最后一個(gè)percentComplete值:
@property (readonly) CGFloat percentComplete;

//過渡動畫的速度傲醉。
/*
此屬性的默認(rèn)值為1.0吐咳,產(chǎn)生一個(gè)實(shí)時(shí)進(jìn)行的動畫沪羔。 可以更改此值以加快或減緩過渡中的動畫死嗦。 例如外盯,在過渡結(jié)束時(shí)或取消動畫時(shí)更改動畫速度狈邑,在這種情況下,您將在停止跟蹤用戶事件并要調(diào)用cancelInteractiveTransition或finishInteractiveTransition方法時(shí)設(shè)置速度蘸嘶。
速度是當(dāng)前動畫速度的乘數(shù)良瞧,因此,大于1.0的值會使動畫加速训唱,而小于1.0的值會使動畫減速褥蚯。 此屬性中的值必須始終大于0.0。
*/
@property (nonatomic,assign) CGFloat completionSpeed;

//指示交互式過渡的動畫完成曲線雪情。
@property (nonatomic,assign) UIViewAnimationCurve completionCurve;

/*
驅(qū)動動畫時(shí)要使用的時(shí)序曲線遵岩。
對于可中斷的動畫你辣,可以指定在繼續(xù)過渡時(shí)要使用的其他時(shí)序曲線提供者巡通。 
*/
@property (nullable, nonatomic, strong)id <UITimingCurveProvider> timingCurve API_AVAILABLE(ios(10.0));
// 一個(gè)布爾值,指示動畫最初是否是交互式的舍哄。
//當(dāng)此屬性的值為YES時(shí)宴凉,交互式動畫將暫停播放,從而使您可以從頭開始驅(qū)動動畫表悬。 當(dāng)您想不交互地開始動畫時(shí)弥锄,可以將此屬性設(shè)置為NO。 
@property (nonatomic) BOOL wantsInteractiveStart API_AVAILABLE(ios(10.0));

/*
這是調(diào)用上下文對象的pauseInteractiveTransition方法的便捷方法蟆沫。 
您可以調(diào)用此方法籽暇,以便可以開始交互式驅(qū)動動畫。 
例如饭庞,當(dāng)用戶的手指觸摸屏幕時(shí)戒悠,手勢處理程序?qū)⒄{(diào)用此方法以停止動畫,然后使用對觸摸位置的更改來更新percentComplete屬性舟山。
*/
- (void)pauseInteractiveTransition API_AVAILABLE(ios(10.0));


/*
調(diào)用上下文對象的updateInteractiveTransition:方法的便捷方法绸狐。
在跟蹤用戶事件時(shí)卤恳,代碼應(yīng)定期調(diào)用此方法以更新當(dāng)前進(jìn)度以完成過渡。
如果在跟蹤過程中寒矿,交互作用超過了您認(rèn)為表示過渡已完成或取消的閾值突琳,停止跟蹤事件并調(diào)用finishInteractiveTransition或cancelInteractiveTransition方法。
*/
- (void)updateInteractiveTransition:(CGFloat)percentComplete;
/*
調(diào)用上下文對象的cancelInteractiveTransition方法的便捷方法符相。
在跟蹤用戶交互時(shí)拆融,當(dāng)交互提示用戶希望取消或中止視圖控制器轉(zhuǎn)換時(shí),手勢識別器或事件處理代碼將調(diào)用此方法啊终。 
例如冠息,如果用戶反轉(zhuǎn)了滑動方向,然后觸摸事件結(jié)束孕索,建議用戶決定是否進(jìn)行過渡逛艰,則可以調(diào)用此方法。
*/
- (void)cancelInteractiveTransition;
/*
這是調(diào)用上下文對象的finishInteractiveTransition方法的便捷方法搞旭。
在跟蹤用戶交互時(shí)散怖,如果交互表明轉(zhuǎn)換已完成,則手勢識別器或事件處理代碼應(yīng)調(diào)用此方法肄渗。
 例如镇眷,如果用戶滑動手指,并且觸摸事件指示滑動距離超過了完成手勢所需的閾值翎嫡,則在相應(yīng)的觸摸事件結(jié)束時(shí)調(diào)用此方法欠动,以使系統(tǒng)知道它現(xiàn)在可以完成過渡。
*/
- (void)finishInteractiveTransition;

@end

參考文章
https://blog.csdn.net/hello_hwc/article/details/42580773
z

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末惑申,一起剝皮案震驚了整個(gè)濱河市具伍,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌圈驼,老刑警劉巖人芽,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異绩脆,居然都是意外死亡萤厅,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門靴迫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來惕味,“玉大人,你說我怎么就攤上這事玉锌∶樱” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵芬沉,是天一觀的道長躺同。 經(jīng)常有香客問我阁猜,道長,這世上最難降的妖魔是什么蹋艺? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任剃袍,我火速辦了婚禮,結(jié)果婚禮上捎谨,老公的妹妹穿的比我還像新娘民效。我一直安慰自己,他們只是感情好涛救,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布畏邢。 她就那樣靜靜地躺著,像睡著了一般检吆。 火紅的嫁衣襯著肌膚如雪舒萎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天蹭沛,我揣著相機(jī)與錄音臂寝,去河邊找鬼。 笑死摊灭,一個(gè)胖子當(dāng)著我的面吹牛咆贬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播帚呼,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼掏缎,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了煤杀?” 一聲冷哼從身側(cè)響起眷蜈,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎怜珍,沒想到半個(gè)月后端蛆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡酥泛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了嫌拣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柔袁。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖异逐,靈堂內(nèi)的尸體忽然破棺而出捶索,到底是詐尸還是另有隱情,我是刑警寧澤灰瞻,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布腥例,位于F島的核電站辅甥,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏燎竖。R本人自食惡果不足惜璃弄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望构回。 院中可真熱鬧夏块,春花似錦、人聲如沸纤掸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽借跪。三九已至政己,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間掏愁,已是汗流浹背匹颤。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留托猩,地道東北人印蓖。 一個(gè)月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像京腥,于是被迫代替她去往敵國和親赦肃。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

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

  • 目錄 ** UIView 動畫 ** ** Core Animation ** ** FaceBook POP動畫...
    方向_4d0d閱讀 1,599評論 0 3
  • 在iOS實(shí)際開發(fā)中常用的動畫無非是以下四種:UIView動畫公浪,核心動畫他宛,幀動畫,自定義轉(zhuǎn)場動畫欠气。 1.UIView...
    請叫我周小帥閱讀 3,094評論 1 23
  • 動畫 - UIKit 動畫原理 視覺殘留效應(yīng) 運(yùn)動模糊 做動畫的時(shí)候要達(dá)到 60FPS 時(shí)候厅各,畫面才能流暢,不然用...
    varlarzh閱讀 799評論 2 10
  • Demo代碼https://github.com/ZeMingXianSheng/CABasicAnimation...
    kakukeme閱讀 693評論 0 50
  • 前言 最近在嘗試一個(gè)翻頁的動畫效果预柒,看了一些資料后队塘,對蘋果的動畫實(shí)現(xiàn)這部分有了一個(gè)比較清楚的了解,僅僅止于比較清楚...
    BigDaddy_閱讀 6,903評論 1 26