一.CoreAnimation介紹
CoreAnimation是一套圖像渲染和動畫基礎框架筛欢,其在iOS和OSX平臺用于顯示對象和實現(xiàn)動畫效果。使用CoreAnimation框架取募,動畫的大部分幀渲染都是蘋果為我們做好的。我們只需要配置幾個動畫參數(shù)(如開始和結束的點)并調用動畫開始的方法。接下來就把剩余的工作交給CoreAnimation,操作全部實際繪圖工作是在圖形渲染硬件加速處理的查吊。這個自動的圖像加速器將會產生高幀頻和順滑的動畫效果而不會加重CPU的負荷、或使APP卡頓湖蜕。
CoreAnimation是在UIKit和APPKit框架之下逻卖,并且被很好的整合到Cocoa和Cocoa Touch的view中。同時CoreAnimation也給出了一些擴展的動畫接口供我們使用昭抒。
下圖是CoreAnimation在cocoa框架中的層級(圖片來自蘋果)
蘋果對于CoreAnimation的介紹中首先講述的是CALayer评也,因為CALayer是視圖顯示的基礎炼杖、同時是CAAnimation動畫產生的的載體。所有的動畫都是作用在CALayer上盗迟,通過更改CALayer的屬性坤邪,將每一幀渲染出來就形成了我們視覺的動畫效果。但是這篇博客主要介紹CAAnimation罚缕,所以直接先忽略了前面的CALayer介紹芜繁,關于CALayer會在下一篇的文章中做詳細介紹。
二.CoreAnimation動畫
上面已經說過了断医,CoreAnimation是一套圖形渲染與動畫框架廷雅,CALayer負責圖形的渲染顯示,而CAAnimation及其子類則負責動畫的實現(xiàn)腌乡。通過CAAnimatin及其子類我們能夠相對簡單的實現(xiàn)一些復雜的layer動畫盟劫。
下面是整個CoreAnimation框架的所有動畫類結構:
1.動畫
CAAnimation是CoreAnimation的抽象超類、而CAPropertyAnimation又是CAAnimation的抽象子類与纽,正如我們所知道的我們不應該直接使用抽象類侣签,而應該使用它們的子類,如CABasicAnimation(基礎動畫)急迂、CAKeyFrameAnimation(關鍵幀動畫)影所、CASpringAnimation(彈簧動畫)等。
1.1 CAAnimation
CAAnimation是CoreAnimation的抽象超類袋毙,也是整個動畫的核心類型檀,大部分的動畫屬性與方法都是在該類中實現(xiàn)的。CAAnimation之所以能夠擁有這些動畫相關的屬性和方法是因為該類遵守了CAMediaTiming听盖、?CAAction兩個協(xié)議胀溺。CAMediaTiming協(xié)議主要實現(xiàn)一些控制動畫執(zhí)行時間的屬性和函數(shù)(包含動畫的開始時間 -> beginTime、執(zhí)行時間 -> duration皆看、執(zhí)行速率 -> speed仓坞、執(zhí)行時間偏移量 -> timeOffset、重復執(zhí)行的次數(shù) -> repeatCount腰吟、動畫執(zhí)行結束的處理 ->filleMode等)无埃,因此CAAnimation能夠很好的處理時間與layer動畫的關系;CAAction主要實現(xiàn)一些動作觸發(fā)的響應接口毛雇,遵守該協(xié)議的對象可以指定CALayer響應的行為嫉称,如添加一個動畫效果,或者執(zhí)行其他的tasks灵疮。
timingFunction:屬性用于設置動畫執(zhí)行的時間步調织阅,創(chuàng)建該對象相對簡單,可以直接使用kCAMediaTimingFunction系列宏指定動畫執(zhí)行的時間為`linear', `easeIn', `easeOut' and `easeInEaseOut'或者也可以使用貝塞爾曲線函數(shù)創(chuàng)建一個CAMediaTimingFunction對象貝塞爾曲線控制點獲取
delegate:設置Animation的代理對象震捣,這樣我們可以獲取動畫執(zhí)行過程的一些狀態(tài)荔棉,包括動畫的開始和結束闹炉,如果你只是想在結束時獲得回調通知,也可以調用setCompletionBlock:函數(shù)润樱,設置動畫完成的block回調渣触。
removedOnCompletion:動畫執(zhí)行結束是否移除動畫,默認YES壹若,但是該參數(shù)必須與fillMode = kCAFillModeForwards 或者 kCAFillModeBoth同時設置才能實現(xiàn)在動畫結束不移除動畫layer嗅钻。
1.2 CAPropertyAnimation
CAPropertyAnimation是CAAnimation的抽象子類,使用該類可以創(chuàng)建一個操作CALayer屬性值的Animation對象舌稀。該類主要實現(xiàn)接口用于指定實現(xiàn)動畫的CALayer的屬性啊犬。
1.3 CABasicAnimation
CABasicAnimation是CAPropertyAnimation的子類,該類實現(xiàn)了三個屬性fromValue壁查、byValue、toValue剔应、用于描述一個單關鍵幀動畫執(zhí)行過程的三個屬性值睡腿。
1.4 CAKeyFrameAnimation
CAKeyFrameAnimation是CAPropertyAnimation的子類,該類用于實現(xiàn)多關鍵幀動畫峻贮。我們可以將動畫主要的一些幀值添加到數(shù)組席怪,賦值給values屬性,再把每一幀對應的時間添加到keyTimes屬性纤控,(值得注意的是keyTimes的值必須在【0挂捻,1】之間,數(shù)組中的值按照數(shù)組的index依次增大船万,并且所有值加在一起的和等于一)刻撒,如果想要為每一幀指定一個CAMediaTimingFunction對象,也可以創(chuàng)建對應的CAMediaTimingFunction對象并加到數(shù)組耿导,然后賦值給timingFunctions屬性声怔。
CAKeyFrameAnimation最強大的地方在于他有一個path屬性,當我們創(chuàng)建一個路徑并賦值給path屬性時舱呻,動畫就會按照我們指定的路徑軌跡執(zhí)行醋火。
1.5 CASpringAnimation
CASpringAnimation繼承于CABasicAnimation類,正如它的名字Spring一樣箱吕,該類主要用于實現(xiàn)一些類似彈簧的動畫效果芥驳。mass屬性相當于物體的重量,stiffness屬性代表了彈簧的剛度茬高,damping屬性代表阻尼系數(shù)兆旬,initialVelocity屬性代表動畫的初始速度,settlingDuration是動畫的預估執(zhí)行時間雅采。通過這些屬性值爵憎,我們可以控制Spring動畫的拉伸幅度慨亲,動畫的執(zhí)行時間等。
2.組動畫
在動畫使用的過程中宝鼓,我們一般不會只使用一個動畫刑棵,我們可能為復雜的動畫效果創(chuàng)建多個Animation對象,然后將這些對象分別添加到Layer動畫中愚铡,這種方式能夠實現(xiàn)但是相對比較麻煩蛉签,我們可以使用組動畫解決這個問題。 對于組合動畫我們可以使用CATransition()和CAAnimationGroup, CAAnimationGroup將多個動畫合并為一組沥寥,并且我們可以指定動畫關聯(lián)時間讓組內的動畫可以同時或者按步驟執(zhí)行碍舍,CATransaction將多個layer-tree更改操作放在一起執(zhí)行并自動更新到render tree。
2.1 CAAnimationGroup
CAAnimationGroup是CAAnimation的子類邑雅,該動畫將多個動畫放到一個animations數(shù)組片橡,添加到layer,這些動畫是并行執(zhí)行的淮野,當然你也可以設置例如beginTime這樣的屬性使動畫按照一定的順序執(zhí)行捧书。
2.2CATransition()
CATransition繼承于CAAnimation,該動畫主要實現(xiàn)一些過渡效果骤星。你可以為type屬性設置`fade', `moveIn', `push' and `reveal'來實現(xiàn)你想要的動畫效果经瓷,同時你也可以設置subtype為`fromLeft', `fromRight', `fromTop' and`fromBottom'來指定動畫的方向。startProgress洞难、endProgress用于控制開始和結束的進度舆吮,范圍必須在【0,1】队贱。
3.動畫執(zhí)行時間
時間是動畫的重要部分之一色冀,我們可以通過CAMediaTiming協(xié)議的方法和屬性指定動畫的時間信息。在CoreAnimation中遵守這個協(xié)議的有兩個類露筒。CAAnimation類采用了這個協(xié)議呐伞,因此可以為Animations執(zhí)行指定時間信息。CALayer類也采用了該協(xié)議慎式,因此也可以為隱式動畫指定Animations執(zhí)行相關的時間信息伶氢,值得注意的是隱式動畫優(yōu)先采用默認的時間信息。
想想時間和動畫的關系瘪吏,理解layer對象是如何和時間相互作用的是非常重要的癣防。每一個layer對象都有一個本地的時間去管理動畫時間。通常在動畫過程中的兩個layer的本地時間非常接近掌眠,接近到我們可能察覺不到有什么不同蕾盯。本地時間可以被父layer或者自己擁有的timing參數(shù)更改
CALayer類定義了convertTime:fromLayer: 和convertTime:toLayer:方法,為了確保時間值適用于layer蓝丙。我們可以使用這些方法將layer的時間值轉換為相對于本地時間或者另一個layer時間值的精確時間级遭。使用這些方法需要考慮到對layer的本地時間的影響望拖,同時這些方法會返回一個可以在其他的layer中使用的值。
一旦我們有了一個layer的本地時間值挫鸽,我們就可以使用這個值去更新Animation對象或者layer的相關屬性说敏,使用CAMediaTiming協(xié)議屬性,我們可以實現(xiàn)一些有趣的動畫效果丢郊,包括:
1.我們可以使用beginTime屬性設置Animation的開始時間盔沫。通常情況,Animations的開始時間是在下一次更新循環(huán)(the next update cycle),但是我們可以設置beginTime參數(shù)來延遲動畫的執(zhí)行時間枫匾。我們可以設置后一個動畫的beginTime為前一個動畫的結束時間架诞,這樣多個動畫按照一定的順序執(zhí)行。
2.使用timeOffset屬性可以在一組動畫中設置相對于其他動畫干茉,延遲執(zhí)行一定的時間段谴忧。
4.動畫的添加與刪除
我們創(chuàng)建好動畫對象可以調用CALayer的addAnimation:forKey:方法將動畫添加到layer上并指定動畫的標記key用于后續(xù)的刪除操作,如果要移除一個動畫可以調用CALayer的removeAnimationForKey:方法移除key值對應的動畫效果角虫、或者你可以調用removeAllAnimations方法刪除layer附帶的所有動畫效果俏蛮,并且remove方法是立即生效的,動畫立即結束執(zhí)行上遥。
三.CoreAnimation動畫實現(xiàn)方式
通過更改Layer的屬性值實現(xiàn)動畫。(屬性必須是Animatable争涌,關于CALayer的可做動畫的屬性)
在這里更改屬性值創(chuàng)建動畫有兩種:
第一種是隱式動畫(Animating a change implicitly),隱式動畫使用默認的時間(0.25秒)和動畫屬性去執(zhí)行動畫粉楚。當我們更改layer的屬性值時,會觸發(fā)隱式動畫亮垫。當修飾的layer對象在layer-tree中時模软,更新會立即執(zhí)行。如果layer對象的顯示效果沒有立即改變饮潦,CoreAnimation會為這些改變創(chuàng)建一個觸發(fā)器并且添加一個或者多個隱式動畫去執(zhí)行燃异。因此,像theLayer.opacity = 0.0继蜡;這樣的更改會引發(fā)CoreAnimation為你創(chuàng)建一個Animation對象回俐,并把這個Animation對象加入到下一次更新循環(huán)(next update cycle.)中去執(zhí)行。
第二種是顯式動畫(Animating a change explicitly)稀并,需要你自己為使用的動畫對象配置屬性仅颇。如上的隱式動畫如果要顯示的執(zhí)行,則需要我們創(chuàng)建一個Animation對象(如:CABasicAnimation)碘举。并為這個對象配置動畫參數(shù)忘瓦。我們可以在把這個Animation添加到layer之前設置Animation的開始和結束值、動畫的執(zhí)行時間引颈、或者設置其他的動畫屬性耕皮。當創(chuàng)建一個Animation對象境蜕,你需要指定動畫的KeyPath并設置動畫參數(shù)。去執(zhí)行動畫時凌停,只需要調用addAnimation:forKey方法去將你想要執(zhí)行的動畫添加到layer上粱年。顯示動畫的layer屬性更新不像隱式動畫,顯示動畫只是創(chuàng)建動畫不會更改layer-tree中的屬性值苦锨。在動畫的結束CoreAnimation會移除動畫并使用它當前的屬性值重繪layer逼泣。如果你想要通過顯示動畫永久更改layer-tree中的屬性值,那么你需要在動畫結束時手動設置layer的屬性舟舒。
隱式動畫和顯示動畫通常是在當前的運行環(huán)(run loop)結束之后執(zhí)行的拉庶,并且當前線程一定要有一個運行環(huán)去執(zhí)行Animations。如果更改多個屬性或者為layer添加Animations秃励,那么這些改變或者添加的動畫是并發(fā)執(zhí)行的氏仗。當然也可以為每個動畫設置特定的執(zhí)行時間,具體的使用下面會有代碼夺鲜。
1.使用UIView的分類實現(xiàn)動畫
盡管我們可以直接使用CAAnimation接口實現(xiàn)想要的動畫效果皆尔,但是對于簡單的動畫使用CAAnimation還是需要額外的步驟,其實蘋果已經為我們做了一些擴展币励,這些擴展在UIView的分類中實現(xiàn)慷蠕,所以對于UIView自帶的layer我們可以直接使用UIView去實現(xiàn)一些簡單的動畫。關于如何實現(xiàn)UIView自帶的layer動畫可以看這里How to Animate Layer-Backed Views.
下面是通過UIView動畫分類接口實現(xiàn)的動畫效果:
1.實現(xiàn)更改view透明度動畫
2.實現(xiàn)更換view背景色動畫并延遲0.5秒執(zhí)行
3.實現(xiàn)view移動動畫
4.實現(xiàn)view旋轉動畫
5.實現(xiàn)view放大縮小動畫
6.實現(xiàn)view彈簧效果動畫
7.實現(xiàn)view系統(tǒng)刪除動畫
8.實現(xiàn)過渡動畫
9.事務實現(xiàn)view翻轉動畫
10.實現(xiàn)view組合動畫
2.使用CAAnimation實現(xiàn)動畫
UIView自帶的動畫是蘋果給我提供的CAAnimation的封裝食呻,其動畫實現(xiàn)相對來說比較簡單方便流炕,我們只需要在block內更改UIView的屬性便可以實現(xiàn)一些簡單的動畫效果。但是其局限性也是十分明顯的仅胞。對于一些復雜動畫每辟、高級動畫UIView自帶的動畫就顯得無能為力,這時CAAnimation的強大之處就無語言表了干旧。其實CAAniamtion動畫的使用也不是很困難渠欺,但是其對于控制動畫執(zhí)行時間、數(shù)學知識運用以及超常的想象力等要求就比較高了椎眯。
下面是對照UIView自帶動畫接口實現(xiàn)的一些動畫挠将,并簡單列舉了幾個動畫效果,對于UIView自帶動畫來說實現(xiàn)相對困難盅视,以此來展示下CAAnimation的強大捐名。
1.實現(xiàn)更改view透明度動畫
2.實現(xiàn)更改view的背景色
3.實現(xiàn)view移動動畫
3.實現(xiàn)view曲線移動
4.實現(xiàn)view旋轉動畫
5.實現(xiàn)viewX軸翻轉動畫
6.實現(xiàn)viewY軸翻轉動畫
7.實現(xiàn)view放大縮小動畫
8.實現(xiàn)view過渡動畫
9.實現(xiàn)view彈簧動畫
10.事務動畫
11.實現(xiàn)view組動畫
四.自定義動畫
上面說了那么多,但是創(chuàng)建的動畫效果都還是比較普通的闹击。對于CAAnimation類族镶蹋,這些只是他們強大功能的冰山一角。但是無論多么復雜的動畫其實都是上面這些基礎動畫的聚合,只要我么能夠想象出動畫的執(zhí)行邏輯贺归,我們就可以使用CAAnimation類族實現(xiàn)相對復雜的動畫淆两。本人的想象力有限,于是我模仿微博的tabbar中間item點擊按鈕的點擊彈出菜單效果拂酣,實現(xiàn)了簡單的彈出菜單秋冰,具體的代碼:clone git代碼。由于不能上傳視頻所以這里就不放效果圖了婶熬,感興趣的可以去下載工程運行試看剑勾。
五.總結
這篇博客主要介紹了CoreAnimation的動畫使用,以及動畫的實現(xiàn)赵颅。雖然CAAnimation類族的使用并不困難虽另,但是還是有很多細節(jié)需要注意的。
1.顯示動畫在執(zhí)行過程中的屬性值修改并不會影響到layer-tree中的layer屬性值饺谬,所以在動畫執(zhí)行結束捂刺,layer會回到原始狀態(tài)。
2. 對于CALayer如果多次調用addAnimation: forKey:只會執(zhí)行最后添加的Animation對象募寨。
3.? 對于一些屬性值不是OC對象的需要將對應的結構體或者基本數(shù)據類型轉化為OC對象族展,比較特殊的是顏色值,要將UIColor轉化為CGColor并對其進行id強轉拔鹰。具體的屬性值轉換下表有對應的轉換對象仪缸。
4.? 其實動畫中比較強大的屬性是CALayer的transform屬性,該屬性可以實現(xiàn)3D動畫效果列肢,蘋果也給出了一些transform的便捷keyPath腹殿,如rotation.x、scale.y例书、translation.z等。
5.?還有一點需要注意的是CAAnimation對象屬性的設置必須在添加到CALayer之前刻炒,否則設置不起作用决采。
做為一個iOS菜鳥希望自己能夠不斷提高自己的擼碼能力的同時,也給大家?guī)砀嗟呢暙I坟奥;馬上就要十一了树瞭, 提前祝大家節(jié)日快樂、happy coding爱谁。?
?終于結束了晒喷,謝謝大家的閱讀!覺得不錯的朋友記得點個喜歡哦访敌!有什么不足的希望大家評論指出凉敲,或者QQ我(1034131730)。
注:以下是一些小的細節(jié)
屬性值得轉換:
當我們創(chuàng)建動畫更改的layer屬性為C語言的結構體時,我們必須將這些結構體轉換為一個對象賦值給layer下面的表列出了C語言類型對應的轉換Obj-C對象爷抓。
CATransform3D的一些便捷的KeyPaths: