CoreAnimation解析及中高級動畫實現

一.CoreAnimation介紹

CoreAnimation是一套圖像渲染和動畫基礎框架,其在iOS和OSX平臺用於顯示對象和實現動畫效果。使用CoreAnimation框架,動畫的大部分幀渲染都是蘋果爲咱們作好的。咱們只須要配置幾個動畫參數(如開始和結束的點)並調用動畫開始的方法。接下來就把剩餘的工做交給CoreAnimation,操做所有實際繪圖工做是在圖形渲染硬件加速處理的。這個自動的圖像加速器將會產生高幀頻和順滑的動畫效果而不會加劇CPU的負荷、或使APP卡頓。
html

CoreAnimation是在UIKit和APPKit框架之下,而且被很好的整合到Cocoa和Cocoa Touch的view中。同時CoreAnimation也給出了一些擴展的動畫接口供咱們使用。git

下圖是CoreAnimation在cocoa框架中的層級(圖片來自蘋果)github


CoreAnimation

蘋果對於CoreAnimation的介紹中首先講述的是CALayer,由於CALayer是視圖顯示的基礎、同時是CAAnimation動畫產生的的載體。全部的動畫都是做用在CALayer上,經過更改CALayer的屬性,將每一幀渲染出來就造成了咱們視覺的動畫效果。可是這篇博客主要介紹CAAnimation,因此直接先忽略了前面的CALayer介紹,關於CALayer會在下一篇的文章中作詳細介紹。
數組

二.CoreAnimation動畫

上面已經說過了,CoreAnimation是一套圖形渲染與動畫框架,CALayer負責圖形的渲染顯示,而CAAnimation及其子類則負責動畫的實現。經過CAAnimatin及其子類咱們可以相對簡單的實現一些複雜的layer動畫。併發

下面是整個CoreAnimation框架的全部動畫類結構:app


動畫類結構

1.動畫

CAAnimationCoreAnimation的抽象超類、而CAPropertyAnimation又是CAAnimation的抽象子類,正如咱們所知道的咱們不該該直接使用抽象類,而應該使用它們的子類,如CABasicAnimation(基礎動畫)、CAKeyFrameAnimation(關鍵幀動畫)、CASpringAnimation(彈簧動畫)等。框架

1.1 CAAnimation

CAAnimationCoreAnimation的抽象超類,也是整個動畫的核心類,大部分的動畫屬性與方法都是在該類中實現的。CAAnimation之因此可以擁有這些動畫相關的屬性和方法是由於該類遵照了CAMediaTiming CAAction兩個協議。CAMediaTiming協議主要實現一些控制動畫執行時間的屬性和函數(包含動畫的開始時間 -> beginTime、執行時間 -> duration、執行速率 -> speed、執行時間偏移量 -> timeOffset、重複執行的次數 -> repeatCount、動畫執行結束的處理 ->filleMode等),所以CAAnimation可以很好的處理時間與layer動畫的關係;CAAction主要實現一些動做觸發的響應接口,遵照該協議的對象能夠指定CALayer響應的行爲,如添加一個動畫效果,或者執行其餘的tasks。ide

timingFunction:屬性用於設置動畫執行的時間步調,建立該對象相對簡單,能夠直接使用kCAMediaTimingFunction系列宏指定動畫執行的時間爲`linear', `easeIn', `easeOut' and `easeInEaseOut'或者也可使用貝塞爾曲線函數建立一個CAMediaTimingFunction對象貝塞爾曲線控制點獲取函數

delegate:設置Animation的代理對象,這樣咱們能夠獲取動畫執行過程的一些狀態,包括動畫的開始和結束,若是你只是想在結束時得到回調通知,也能夠調用setCompletionBlock:函數,設置動畫完成的block回調。oop

removedOnCompletion:動畫執行結束是否移除動畫,默認YES,可是該參數必須與fillMode = kCAFillModeForwards 或者 kCAFillModeBoth同時設置才能實如今動畫結束不移除動畫layer。

1.2 CAPropertyAnimation

CAPropertyAnimationCAAnimation的抽象子類,使用該類能夠建立一個操做CALayer屬性值的Animation對象。該類主要實現接口用於指定實現動畫的CALayer的屬性。

1.3 CABasicAnimation

CABasicAnimationCAPropertyAnimation的子類,該類實現了三個屬性fromValue、byValue、toValue、用於描述一個單關鍵幀動畫執行過程的三個屬性值。

1.4 CAKeyFrameAnimation

CAKeyFrameAnimationCAPropertyAnimation的子類,該類用於實現多關鍵幀動畫。咱們能夠將動畫主要的一些幀值添加到數組,賦值給values屬性,再把每一幀對應的時間添加到keyTimes屬性,(值得注意的是keyTimes的值必須在【0,1】之間,數組中的值按照數組的index依次增大,而且全部值加在一塊兒的和等於一),若是想要爲每一幀指定一個CAMediaTimingFunction對象,也能夠建立對應的CAMediaTimingFunction對象並加到數組,而後賦值給timingFunctions屬性。

CAKeyFrameAnimation最強大的地方在於他有一個path屬性,當咱們建立一個路徑並賦值給path屬性時,動畫就會按照咱們指定的路徑軌跡執行。

1.5 CASpringAnimation

CASpringAnimation繼承於CABasicAnimation類,正如它的名字Spring同樣,該類主要用於實現一些相似彈簧的動畫效果。mass屬性至關於物體的重量,stiffness屬性表明了彈簧的剛度,damping屬性表明阻尼係數,initialVelocity屬性表明動畫的初始速度,settlingDuration是動畫的預估執行時間。經過這些屬性值,咱們能夠控制Spring動畫的拉伸幅度,動畫的執行時間等。

2.組動畫

在動畫使用的過程當中,咱們通常不會只使用一個動畫,咱們可能爲複雜的動畫效果建立多個Animation對象,而後將這些對象分別添加到Layer動畫中,這種方式可以實現可是相對比較麻煩,咱們可使用組動畫解決這個問題。 對於組合動畫咱們可使用CATransition()和CAAnimationGroup, CAAnimationGroup將多個動畫合併爲一組,而且咱們能夠指定動畫關聯時間讓組內的動畫能夠同時或者按步驟執行,CATransaction將多個layer-tree更改操做放在一塊兒執行並自動更新到render tree。

2.1 CAAnimationGroup

CAAnimationGroupCAAnimation的子類,該動畫將多個動畫放到一個animations數組,添加到layer,這些動畫是並行執行的,固然你也能夠設置例如beginTime這樣的屬性使動畫按照必定的順序執行。

2.2CATransition()

CATransition繼承於CAAnimation,該動畫主要實現一些過渡效果。你能夠爲type屬性設置`fade', `moveIn', `push' and `reveal'來實現你想要的動畫效果,同時你也能夠設置subtype爲`fromLeft', `fromRight', `fromTop' and`fromBottom'來指定動畫的方向。startProgressendProgress用於控制開始和結束的進度,範圍必須在【0,1】。

3.動畫執行時間

時間是動畫的重要部分之一,咱們能夠經過CAMediaTiming協議的方法和屬性指定動畫的時間信息。在CoreAnimation中遵照這個協議的有兩個類。CAAnimation類採用了這個協議,所以能夠爲Animations執行指定時間信息。CALayer類也採用了該協議,所以也能夠爲隱式動畫指定Animations執行相關的時間信息,值得注意的是隱式動畫優先採用默認的時間信息。

想一想時間和動畫的關係,理解layer對象是如何和時間相互做用的是很是重要的。每個layer對象都有一個本地的時間去管理動畫時間。一般在動畫過程當中的兩個layer的本地時間很是接近,接近到咱們可能察覺不到有什麼不一樣。本地時間能夠被父layer或者本身擁有的timing參數更改

CALayer類定義了convertTime:fromLayer: convertTime:toLayer:方法,爲了確保時間值適用於layer。咱們可使用這些方法將layer的時間值轉換爲相對於本地時間或者另外一個layer時間值的精確時間。使用這些方法須要考慮到對layer的本地時間的影響,同時這些方法會返回一個能夠在其餘的layer中使用的值。

一旦咱們有了一個layer的本地時間值,咱們就可使用這個值去更新Animation對象或者layer的相關屬性,使用CAMediaTiming協議屬性,咱們能夠實現一些有趣的動畫效果,包括:

1.咱們可使用beginTime屬性設置Animation的開始時間。一般狀況,Animations的開始時間是在下一次更新循環(the next update cycle),可是咱們能夠設置beginTime參數來延遲動畫的執行時間。咱們能夠設置後一個動畫的beginTime爲前一個動畫的結束時間,這樣多個動畫按照必定的順序執行。

2.使用timeOffset屬性能夠在一組動畫中設置相對於其餘動畫,延遲執行必定的時間段。

4.動畫的添加與刪除

咱們建立好動畫對象能夠調用CALayeraddAnimation:forKey:方法將動畫添加到layer上並指定動畫的標記key用於後續的刪除操做,若是要移除一個動畫能夠調用CALayerremoveAnimationForKey:方法移除key值對應的動畫效果、或者你能夠調用removeAllAnimations方法刪除layer附帶的全部動畫效果,而且remove方法是當即生效的,動畫當即結束執行。

三.CoreAnimation動畫實現方式

經過更改Layer的屬性值實現動畫。(屬性必須是Animatable關於CALayer的可作動畫的屬性)

在這裏更改屬性值建立動畫有兩種:

第一種是隱式動畫(Animating a change implicitly),隱式動畫使用默認的時間(0.25秒)和動畫屬性去執行動畫。當咱們更改layer的屬性值時,會觸發隱式動畫。當修飾的layer對象在layer-tree中時,更新會當即執行。若是layer對象的顯示效果沒有當即改變,CoreAnimation會爲這些改變建立一個觸發器而且添加一個或者多個隱式動畫去執行。所以,像theLayer.opacity = 0.0;這樣的更改會引起CoreAnimation爲你建立一個Animation對象,並把這個Animation對象加入到下一次更新循環(next update cycle.)中去執行。

第二種是顯式動畫(Animating a change explicitly),須要你本身爲使用的動畫對象配置屬性。如上的隱式動畫若是要顯示的執行,則須要咱們建立一個Animation對象(如:CABasicAnimation)。併爲這個對象配置動畫參數。咱們能夠在把這個Animation添加到layer以前設置Animation的開始和結束值、動畫的執行時間、或者設置其餘的動畫屬性。當建立一個Animation對象,你須要指定動畫的KeyPath並設置動畫參數。去執行動畫時,只須要調用addAnimation:forKey方法去將你想要執行的動畫添加到layer上。顯示動畫的layer屬性更新不像隱式動畫,顯示動畫只是建立動畫不會更改layer-tree中的屬性值。在動畫的結束CoreAnimation會移除動畫並使用它當前的屬性值重繪layer。若是你想要經過顯示動畫永久更改layer-tree中的屬性值,那麼你須要在動畫結束時手動設置layer的屬性。

隱式動畫和顯示動畫一般是在當前的運行環(run loop)結束以後執行的,而且當前線程必定要有一個運行環去執行Animations。若是更改多個屬性或者爲layer添加Animations,那麼這些改變或者添加的動畫是併發執行的。固然也能夠爲每一個動畫設置特定的執行時間,具體的使用下面會有代碼。

1.使用UIView的分類實現動畫

儘管咱們能夠直接使用CAAnimation接口實現想要的動畫效果,可是對於簡單的動畫使用CAAnimation仍是須要額外的步驟,其實蘋果已經爲咱們作了一些擴展,這些擴展在UIView的分類中實現,因此對於UIView自帶的layer咱們能夠直接使用UIView去實現一些簡單的動畫。關於如何實現UIView自帶的layer動畫能夠看這裏How to Animate Layer-Backed Views.

下面是經過UIView動畫分類接口實現的動畫效果:

1.實現更改view透明度動畫


透明度

2.實現更換view背景色動畫並延遲0.5秒執行


背景色

3.實現view移動動畫


移動

4.實現view旋轉動畫


旋轉

5.實現view放大縮小動畫


放大

縮小

6.實現view彈簧效果動畫


彈簧

7.實現view系統刪除動畫


系統刪除

8.實現過渡動畫


過渡

9.事務實現view翻轉動畫


事務翻轉

10.實現view組合動畫


UIView組合動畫


2.使用CAAnimation實現動畫

UIView自帶的動畫是蘋果給我提供的CAAnimation的封裝,其動畫實現相對來講比較簡單方便,咱們只須要在block內更改UIView的屬性即可以實現一些簡單的動畫效果。可是其侷限性也是十分明顯的。對於一些複雜動畫、高級動畫UIView自帶的動畫就顯得無能爲力,這時CAAnimation的強大之處就無語言表了。其實CAAniamtion動畫的使用也不是很困難,可是其對於控制動畫執行時間、數學知識運用以及超常的想象力等要求就比較高了。

下面是對照UIView自帶動畫接口實現的一些動畫,並簡單列舉了幾個動畫效果,對於UIView自帶動畫來講實現相對困難,以此來展現下CAAnimation的強大。

1.實現更改view透明度動畫


透明度

2.實現更改view的背景色


背景色

3.實現view移動動畫


移動

3.實現view曲線移動


曲線移動

4.實現view旋轉動畫


旋轉

5.實現viewX軸翻轉動畫


X軸翻轉

6.實現viewY軸翻轉動畫


Y軸翻轉

7.實現view放大縮小動畫


放大

縮小

函數實現

8.實現view過渡動畫


過渡

函數實現

9.實現view彈簧動畫


彈簧動畫

函數實現

10.事務動畫


事務

11.實現view組動畫


組動畫

函數實現

四.自定義動畫

上面說了那麼多,可是建立的動畫效果都仍是比較普通的。對於CAAnimation類族,這些只是他們強大功能的冰山一角。可是不管多麼複雜的動畫其實都是上面這些基礎動畫的聚合,只要我麼可以想象出動畫的執行邏輯,咱們就可使用CAAnimation類族實現相對複雜的動畫。本人的想象力有限,因而我模仿微博的tabbar中間item點擊按鈕的點擊彈出菜單效果,實現了簡單的彈出菜單,具體的代碼:clone git代碼。因爲不能上傳視頻因此這裏就不放效果圖了,感興趣的能夠去下載工程運行試看。

五.總結

這篇博客主要介紹了CoreAnimation的動畫使用,以及動畫的實現。雖然CAAnimation類族的使用並不困難,可是仍是有不少細節須要注意的。

1.顯示動畫在執行過程當中的屬性值修改並不會影響到layer-tree中的layer屬性值,因此在動畫執行結束,layer會回到原始狀態。

2. 對於CALayer若是屢次調用addAnimation: forKey:只會執行最後添加的Animation對象。

3. 對於一些屬性值不是OC對象的須要將對應的結構體或者基本數據類型轉化爲OC對象,比較特殊的是顏色值,要將UIColor轉化爲CGColor並對其進行id強轉。具體的屬性值轉換下表有對應的轉換對象。

4. 其實動畫中比較強大的屬性是CALayertransform屬性,該屬性能夠實現3D動畫效果,蘋果也給出了一些transform的便捷keyPath,如rotation.xscale.ytranslation.z等。

5. 還有一點須要注意的是CAAnimation對象屬性的設置必須在添加到CALayer以前,不然設置不起做用。

作爲一個iOS菜鳥但願本身可以不斷提升本身的擼碼能力的同時,也給你們帶來更多的貢獻;立刻就要十一了, 提早祝你們節日快樂、happy coding。

終於結束了,謝謝你們的閱讀!以爲不錯的朋友記得點個喜歡哦!有什麼不足的但願你們評論指出,或者QQ我(1034131730)。


注:如下是一些小的細節

屬性值得轉換:

當咱們建立動畫更改的layer屬性爲C語言的結構體時,咱們必須將這些結構體轉換爲一個對象賦值給layer下面的表列出了C語言類型對應的轉換Obj-C對象。


動畫屬性值轉換

CATransform3D的一些便捷的KeyPaths:


CATransform3D
相關文章
相關標籤/搜索