概覽
在iOS中隨處都可以看到絢麗的動(dòng)畫效果未桥,實(shí)現(xiàn)這些動(dòng)畫的過(guò)程并不復(fù)雜送悔,今天將帶大家一窺iOS動(dòng)畫全貌扯再。在這里你可以看到iOS中如何使用圖層精簡(jiǎn)非交互式繪圖传黄,如何通過(guò)核心動(dòng)畫創(chuàng)建基礎(chǔ)動(dòng)畫、關(guān)鍵幀動(dòng)畫凤壁、動(dòng)畫組吩屹、轉(zhuǎn)場(chǎng)動(dòng)畫,如何通過(guò)UIView的裝飾方法對(duì)這些動(dòng)畫操作進(jìn)行簡(jiǎn)化等拧抖。在今天的文章里您可以看到動(dòng)畫操作在iOS中是如何簡(jiǎn)單和高效煤搜,很多原來(lái)想做但是苦于沒(méi)有思路的動(dòng)畫在iOS中將變得越發(fā)簡(jiǎn)單:
? ?1.1 CALayer簡(jiǎn)介
? ?1.2 CALayer常用屬性
? ?1.3 CALayer繪圖
? ? 2.1 基礎(chǔ)動(dòng)畫
? ? 2.2 關(guān)鍵幀動(dòng)畫
? ? 2.3 動(dòng)畫組
? ? 2.4 轉(zhuǎn)場(chǎng)動(dòng)畫
? ? 2.5 逐幀動(dòng)畫
3?UIView動(dòng)畫封裝?
1?CALayer
1.1 CALayer簡(jiǎn)介
在介紹動(dòng)畫操作之前我們必須先來(lái)了解一個(gè)動(dòng)畫中常用的對(duì)象CALayer。CALayer包含在QuartzCore框架中唧席,這是一個(gè)跨平臺(tái)的框架擦盾,既可以用在iOS中又可以用在Mac OS X中。在使用Core Animation開(kāi)發(fā)動(dòng)畫的本質(zhì)就是將CALayer中的內(nèi)容轉(zhuǎn)化為位圖從而供硬件操作淌哟,所以要熟練掌握動(dòng)畫操作必須先來(lái)熟悉CALayer迹卢。
在上一篇文章中使用Quartz 2D繪圖時(shí)大家其實(shí)已經(jīng)用到了CALayer,當(dāng)利用drawRect:方法繪圖的本質(zhì)就是繪制到了UIView的layer(屬性)中徒仓,可是這個(gè)過(guò)程大家在上一節(jié)中根本體會(huì)不到腐碱。但是在Core Animation中我們操作更多的則不再是UIView而是直接面對(duì)CALayer。下圖描繪了CALayer和UIView的關(guān)系掉弛,在UIView中有一個(gè)layer屬性作為根圖層症见,根圖層上可以放其他子圖層喂走,在UIView中所有能夠看到的內(nèi)容都包含在layer中:
1.2 CALayer常用屬性
在iOS中CALayer的設(shè)計(jì)主要是了為了內(nèi)容展示和動(dòng)畫操作,CALayer本身并不包含在UIKit中筒饰,它不能響應(yīng)事件。由于CALayer在設(shè)計(jì)之初就考慮它的動(dòng)畫操作功能壁晒,CALayer很多屬性在修改時(shí)都能形成動(dòng)畫效果瓷们,這種屬性稱為“隱式動(dòng)畫屬性”。但是對(duì)于UIView的根圖層而言屬性的修改并不形成動(dòng)畫效果秒咐,因?yàn)楹芏嗲闆r下根圖層更多的充當(dāng)容器的做用谬晕,如果它的屬性變動(dòng)形成動(dòng)畫效果會(huì)直接影響子圖層。另外携取,UIView的根圖層創(chuàng)建工作完全由iOS負(fù)責(zé)完成攒钳,無(wú)法重新創(chuàng)建,但是可以往根圖層中添加子圖層或移除子圖層雷滋。
下表列出了CALayer常用的屬性:
·隱式屬性動(dòng)畫的本質(zhì)是這些屬性的變動(dòng)默認(rèn)隱含了CABasicAnimation動(dòng)畫實(shí)現(xiàn)不撑,詳情大家可以參照Xcode幫助文檔中“Animatable Properties”一節(jié)。
·在CALayer中很少使用frame屬性晤斩,因?yàn)閒rame本身不支持動(dòng)畫效果焕檬,通常使用bounds和position代替。
·CALayer中透明度使用opacity表示而不是alpha澳泵;中心點(diǎn)使用position表示而不是center实愚。
·anchorPoint屬性是圖層的錨點(diǎn),范圍在(0~1,0~1)表示在x兔辅、y軸的比例腊敲,這個(gè)點(diǎn)永遠(yuǎn)可以同position(中心點(diǎn))重合,當(dāng)圖層中心點(diǎn)固定后,調(diào)整 ? ? ? ?anchorPoint即可達(dá)到調(diào)整圖層顯示位置的作用(因?yàn)樗肋h(yuǎn)和position重合)
為了進(jìn)一步說(shuō)明anchorPoint的作用匕荸,假設(shè)有一個(gè)層大小100*100苔悦,現(xiàn)在中心點(diǎn)位置(50,50),由此可以得出frame(0,0,100,100)乎赴。上面說(shuō)過(guò)anchorPoint默認(rèn)為(0.5,0.5),同中心點(diǎn)position重合潮尝,此時(shí)使用圖形描述如圖1榕吼;當(dāng)修改anchorPoint為(0,0),此時(shí)錨點(diǎn)處于圖層左上角勉失,但是中心點(diǎn)poition并不會(huì)改變羹蚣,因此圖層會(huì)向右下角移動(dòng),如圖2乱凿;然后修改anchorPoint為(1,1,)顽素,position還是保持位置不變咽弦,錨點(diǎn)處于圖層右下角,此時(shí)圖層如圖3胁出。
下面通過(guò)一個(gè)簡(jiǎn)單的例子演示一下上面幾個(gè)屬性型型,程序初始化階段我們定義一個(gè)正方形,但是圓角路徑調(diào)整為正方形邊長(zhǎng)的一般全蝶,使其看起來(lái)是一個(gè)圓形闹蒜,在點(diǎn)擊屏幕的時(shí)候修改圖層的屬性形成動(dòng)畫效果(注意在程序中沒(méi)有直接修改UIView的layer屬性,因?yàn)楦鶊D層無(wú)法形成動(dòng)畫效果):
運(yùn)行效果:
1.3 CALayer繪圖
上一篇文章中重點(diǎn)討論了使用Quartz 2D繪圖抑淫,當(dāng)時(shí)調(diào)用了UIView的drawRect:方法繪制圖形绷落、圖像,這種方式本質(zhì)還是在圖層中繪制始苇,但是這里會(huì)著重介紹一下如何直接在圖層中繪圖砌烁。在圖層中繪圖的方式跟原來(lái)基本沒(méi)有區(qū)別,只是drawRect:方法是由UIKit組件進(jìn)行調(diào)用催式,因此里面可以使用一些UIKit封裝的方法進(jìn)行繪圖函喉,而直接繪制到圖層的方法由于并非UIKit直接調(diào)用因此只能用原生的Core Graphics方法繪制。
圖層繪圖有兩種方法荣月,不管使用哪種方法繪制完必須調(diào)用圖層的setNeedDisplay方法(注意是圖層的方法函似,不是UIView的方法,前面我們介紹過(guò)UIView也有此方法)
通過(guò)圖層代理drawLayer: inContext:方法繪制
通過(guò)自定義圖層drawInContext:方法繪制
使用代理方法繪圖
通過(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ú)法顯示咽白。
下面的代碼演示了在一個(gè)自定義圖層繪制一張圖像并將圖像設(shè)置成圓形啤握,這種效果在很多應(yīng)用中很常見(jiàn),如最新版的手機(jī)QQ頭像就是這種效果:
使用代理方法繪制圖形晶框、圖像時(shí)在drawLayer:inContext:方法中可以通過(guò)事件參數(shù)獲得繪制的圖層和圖形上下文排抬。在這個(gè)方法中繪圖時(shí)所有的位置都是相對(duì)于圖層而言的,圖形上下文指的也是當(dāng)前圖層的圖形上下文授段。
需要注意的是上面代碼中繪制圖片圓形裁切效果時(shí)如果不設(shè)置masksToBounds是無(wú)法顯示圓形蹲蒲,但是對(duì)于其他圖形卻沒(méi)有這個(gè)限制。原因就是當(dāng)繪制一張圖片到圖層上的時(shí)候會(huì)重新創(chuàng)建一個(gè)圖層添加到當(dāng)前圖層侵贵,這樣一來(lái)如果設(shè)置了圓角之后雖然底圖層有圓角效果届搁,但是子圖層還是矩形,只有設(shè)置了masksToBounds為YES讓子圖層按底圖層剪切才能顯示圓角效果。同樣的卡睦,有些朋友經(jīng)常在網(wǎng)上提問(wèn)說(shuō)為什么使用UIImageView的layer設(shè)置圓角后圖片無(wú)法顯示圓角宴胧,只有設(shè)置masksToBounds才能出現(xiàn)效果,也是類似的問(wèn)題表锻。
2?Core Animation
大家都知道在iOS中實(shí)現(xiàn)一個(gè)動(dòng)畫相當(dāng)簡(jiǎn)單恕齐,只要調(diào)用UIView的塊代碼即可實(shí)現(xiàn)一個(gè)動(dòng)畫效果,這在其他系統(tǒng)開(kāi)發(fā)中基本不可能實(shí)現(xiàn)瞬逊。下面通過(guò)一個(gè)簡(jiǎn)單的UIView進(jìn)行一個(gè)圖片放大動(dòng)畫效果演示:
使用上面UIView封裝的方法進(jìn)行動(dòng)畫設(shè)置固然十分方便显歧,但是具體動(dòng)畫如何實(shí)現(xiàn)我們是不清楚的,而且上面的代碼還有一些問(wèn)題是無(wú)法解決的码耐,例如:如何控制動(dòng)畫的暫停追迟?如何進(jìn)行動(dòng)畫的組合溶其?骚腥。。瓶逃。
這里就需要了解iOS的核心動(dòng)畫Core Animation(包含在Quartz Core框架中)束铭。在iOS中核心動(dòng)畫分為幾類:基礎(chǔ)動(dòng)畫、關(guān)鍵幀動(dòng)畫厢绝、動(dòng)畫組契沫、轉(zhuǎn)場(chǎng)動(dòng)畫。各個(gè)類的關(guān)系大致如下:
CAAnimation:核心動(dòng)畫的基礎(chǔ)類昔汉,不能直接使用懈万,負(fù)責(zé)動(dòng)畫運(yùn)行時(shí)間、速度的控制靶病,本身實(shí)現(xiàn)了CAMediaTiming協(xié)議会通。
CAPropertyAnimation:屬性動(dòng)畫的基類(通過(guò)屬性進(jìn)行動(dòng)畫設(shè)置,注意是可動(dòng)畫屬性)娄周,不能直接使用涕侈。
CAAnimationGroup:動(dòng)畫組,動(dòng)畫組是一種組合模式設(shè)計(jì)煤辨,可以通過(guò)動(dòng)畫組來(lái)進(jìn)行所有動(dòng)畫行為的統(tǒng)一控制裳涛,組中所有動(dòng)畫效果可以并發(fā)執(zhí)行。
CATransition:轉(zhuǎn)場(chǎng)動(dòng)畫众辨,主要通過(guò)濾鏡進(jìn)行動(dòng)畫效果設(shè)置端三。
CABasicAnimation:基礎(chǔ)動(dòng)畫,通過(guò)屬性修改進(jìn)行動(dòng)畫參數(shù)控制鹃彻,只有初始狀態(tài)和結(jié)束狀態(tài)技肩。
CAKeyframeAnimation:關(guān)鍵幀動(dòng)畫,同樣是通過(guò)屬性進(jìn)行動(dòng)畫參數(shù)控制,但是同基礎(chǔ)動(dòng)畫不同的是它可以有多個(gè)狀態(tài)控制虚婿。
基礎(chǔ)動(dòng)畫旋奢、關(guān)鍵幀動(dòng)畫都屬于屬性動(dòng)畫,就是通過(guò)修改屬性值產(chǎn)生動(dòng)畫效果然痊,開(kāi)發(fā)人員只需要設(shè)置初始值和結(jié)束值至朗,中間的過(guò)程動(dòng)畫(又叫“補(bǔ)間動(dòng)畫”)由系統(tǒng)自動(dòng)計(jì)算產(chǎn)生。和基礎(chǔ)動(dòng)畫不同的是關(guān)鍵幀動(dòng)畫可以設(shè)置多個(gè)屬性值剧浸,每?jī)蓚€(gè)屬性中間的補(bǔ)間動(dòng)畫由系統(tǒng)自動(dòng)完成锹引,因此從這個(gè)角度而言基礎(chǔ)動(dòng)畫又可以看成是有兩個(gè)關(guān)鍵幀的關(guān)鍵幀動(dòng)畫。
2.1 基礎(chǔ)動(dòng)畫
在開(kāi)發(fā)過(guò)程中很多情況下通過(guò)基礎(chǔ)動(dòng)畫就可以滿足開(kāi)發(fā)需求唆香,前面例子中使用的UIView代碼塊進(jìn)行圖像放大縮小的演示動(dòng)畫也是基礎(chǔ)動(dòng)畫(在iOS7中UIView也對(duì)關(guān)鍵幀動(dòng)畫進(jìn)行了封裝)嫌变,只是UIView裝飾方法隱藏了更多的細(xì)節(jié)。如果不使用UIView封裝的方法躬它,動(dòng)畫創(chuàng)建一般分為以下幾步:
1.初始化動(dòng)畫并設(shè)置動(dòng)畫屬性
2.設(shè)置動(dòng)畫屬性初始值(可以省略)腾啥、結(jié)束值以及其他動(dòng)畫屬性
3.給圖層添加動(dòng)畫
下面以一個(gè)移動(dòng)動(dòng)畫為例進(jìn)行演示,在這個(gè)例子中點(diǎn)擊屏幕哪個(gè)位置落花將飛向哪里冯吓。
運(yùn)行效果:
上面實(shí)現(xiàn)了一個(gè)基本動(dòng)畫效果倘待,但是這個(gè)動(dòng)畫存在一個(gè)問(wèn)題:動(dòng)畫結(jié)束后動(dòng)畫圖層回到了原來(lái)的位置,當(dāng)然是用UIView封裝的方法是沒(méi)有這個(gè)問(wèn)題的组贺。如何解決這個(gè)問(wèn)題呢凸舵?
前面說(shuō)過(guò)圖層動(dòng)畫的本質(zhì)就是將圖層內(nèi)部的內(nèi)容轉(zhuǎn)化為位圖經(jīng)硬件操作形成一種動(dòng)畫效果,其實(shí)圖層本身并沒(méi)有任何的變化失尖。上面的動(dòng)畫中圖層并沒(méi)有因?yàn)閯?dòng)畫效果而改變它的位置(對(duì)于縮放動(dòng)畫其大小也是不會(huì)改變的)啊奄,所以動(dòng)畫完成之后圖層還是在原來(lái)的顯示位置沒(méi)有任何變化,如果這個(gè)圖層在一個(gè)UIView中你會(huì)發(fā)現(xiàn)在UIView移動(dòng)過(guò)程中你要觸發(fā)UIView的點(diǎn)擊事件也只能點(diǎn)擊原來(lái)的位置(即使它已經(jīng)運(yùn)動(dòng)到了別的位置)掀潮,因?yàn)樗奈恢脧膩?lái)沒(méi)有變過(guò)菇夸。當(dāng)然解決這個(gè)問(wèn)題方法比較多,這里不妨在動(dòng)畫完成之后重新設(shè)置它的位置胧辽。
上面通過(guò)給動(dòng)畫設(shè)置一個(gè)代理去監(jiān)聽(tīng)動(dòng)畫的開(kāi)始和結(jié)束事件峻仇,在動(dòng)畫開(kāi)始前給動(dòng)畫添加一個(gè)自定義屬性“KCBasicAnimationLocation”存儲(chǔ)動(dòng)畫終點(diǎn)位置,然后在動(dòng)畫結(jié)束后設(shè)置動(dòng)畫的位置為終點(diǎn)位置邑商。
如果運(yùn)行上面的代碼大家可能會(huì)發(fā)現(xiàn)另外一個(gè)問(wèn)題摄咆,那就是動(dòng)畫運(yùn)行完成后會(huì)重新從起始點(diǎn)運(yùn)動(dòng)到終點(diǎn)。這個(gè)問(wèn)題產(chǎn)生的原因就是前面提到的人断,對(duì)于非根圖層吭从,設(shè)置圖層的可動(dòng)畫屬性(在動(dòng)畫結(jié)束后重新設(shè)置了position,而position是可動(dòng)畫屬性)會(huì)產(chǎn)生動(dòng)畫效果恶迈。解決這個(gè)問(wèn)題有兩種辦法:關(guān)閉圖層隱式動(dòng)畫涩金、設(shè)置動(dòng)畫圖層為根圖層谱醇。顯然這里不能采取后者,因?yàn)楦鶊D層當(dāng)前已經(jīng)作為動(dòng)畫的背景步做。
要關(guān)閉隱式動(dòng)畫需要用到動(dòng)畫事務(wù)CATransaction副渴,在事務(wù)內(nèi)將隱式動(dòng)畫關(guān)閉,例如上面的代碼可以改為:
當(dāng)然上面的動(dòng)畫還顯得有些生硬全度,因?yàn)槁浠h散的時(shí)候可能不僅僅是自由落體運(yùn)動(dòng)煮剧,本身由于空氣阻力、外界風(fēng)力還會(huì)造成落花在空中的旋轉(zhuǎn)将鸵、搖擺等勉盅,這里不妨給圖層添加一個(gè)旋轉(zhuǎn)的動(dòng)畫。對(duì)于圖層的旋轉(zhuǎn)前面已經(jīng)演示過(guò)怎么通過(guò)key path設(shè)置圖層旋轉(zhuǎn)的內(nèi)容了顶掉,在這里需要強(qiáng)調(diào)一下草娜,圖層的形變都是基于錨點(diǎn)進(jìn)行的。例如旋轉(zhuǎn)痒筒,旋轉(zhuǎn)的中心點(diǎn)就是圖層的錨點(diǎn)宰闰。
上面代碼中結(jié)合兩種動(dòng)畫操作,需要注意的是只給移動(dòng)動(dòng)畫設(shè)置了代理凸克,在旋轉(zhuǎn)動(dòng)畫中并沒(méi)有設(shè)置代理议蟆,否則代理方法會(huì)執(zhí)行兩遍闷沥。由于旋轉(zhuǎn)動(dòng)畫會(huì)無(wú)限循環(huán)執(zhí)行(上面設(shè)置了重復(fù)次數(shù)無(wú)窮大)萎战,并且兩個(gè)動(dòng)畫的執(zhí)行時(shí)間沒(méi)有必然的關(guān)系,這樣一來(lái)移動(dòng)停止后可能還在旋轉(zhuǎn)舆逃,為了讓移動(dòng)動(dòng)畫停止后旋轉(zhuǎn)動(dòng)畫停止就需要使用到動(dòng)畫的暫停和恢復(fù)方法蚂维。
核心動(dòng)畫的運(yùn)行有一個(gè)媒體時(shí)間的概念,假設(shè)將一個(gè)旋轉(zhuǎn)動(dòng)畫設(shè)置旋轉(zhuǎn)一周用時(shí)60秒的話路狮,那么當(dāng)動(dòng)畫旋轉(zhuǎn)90度后媒體時(shí)間就是15秒虫啥。如果此時(shí)要將動(dòng)畫暫停只需要讓媒體時(shí)間偏移量設(shè)置為15秒即可,并把動(dòng)畫運(yùn)行速度設(shè)置為0使其停止運(yùn)動(dòng)奄妨。類似的涂籽,如果又過(guò)了60秒后需要恢復(fù)動(dòng)畫(此時(shí)媒體時(shí)間為75秒),這時(shí)只要將動(dòng)畫開(kāi)始開(kāi)始時(shí)間設(shè)置為當(dāng)前媒體時(shí)間75秒減去暫停時(shí)的時(shí)間(也就是之前定格動(dòng)畫時(shí)的偏移量)15秒(開(kāi)始時(shí)間=75-15=60秒)砸抛,那么動(dòng)畫就會(huì)重新計(jì)算60秒后的狀態(tài)再開(kāi)始運(yùn)行评雌,與此同時(shí)將偏移量重新設(shè)置為0并且把運(yùn)行速度設(shè)置1。這個(gè)過(guò)程中真正起到暫停動(dòng)畫和恢復(fù)動(dòng)畫的其實(shí)是動(dòng)畫速度的調(diào)整直焙,媒體時(shí)間偏移量以及恢復(fù)時(shí)的開(kāi)始時(shí)間設(shè)置主要為了讓動(dòng)畫更加連貫景东。
下面的代碼演示了移動(dòng)動(dòng)畫結(jié)束后旋轉(zhuǎn)動(dòng)畫暫停,并且當(dāng)再次點(diǎn)擊動(dòng)畫時(shí)旋轉(zhuǎn)恢復(fù)的過(guò)程(注意在移動(dòng)過(guò)程中如果再次點(diǎn)擊屏幕可以暫停移動(dòng)和旋轉(zhuǎn)動(dòng)畫奔誓,再次點(diǎn)擊可以恢復(fù)兩種動(dòng)畫斤吐。但是當(dāng)移動(dòng)結(jié)束后觸發(fā)了移動(dòng)動(dòng)畫的完成事件如果再次點(diǎn)擊屏幕則只能恢復(fù)旋轉(zhuǎn)動(dòng)畫,因?yàn)榇藭r(shí)移動(dòng)動(dòng)畫已經(jīng)結(jié)束而不是暫停,無(wú)法再恢復(fù))和措。
運(yùn)行效果:
2.2 關(guān)鍵幀動(dòng)畫
熟悉flash開(kāi)發(fā)的朋友對(duì)于關(guān)鍵幀動(dòng)畫應(yīng)該不陌生,這種動(dòng)畫方式在flash開(kāi)發(fā)中經(jīng)常用到颁褂。關(guān)鍵幀動(dòng)畫就是在動(dòng)畫控制過(guò)程中開(kāi)發(fā)者指定主要的動(dòng)畫狀態(tài)故响,至于各個(gè)狀態(tài)間動(dòng)畫如何進(jìn)行則由系統(tǒng)自動(dòng)運(yùn)算補(bǔ)充(每?jī)蓚€(gè)關(guān)鍵幀之間系統(tǒng)形成的動(dòng)畫稱為“補(bǔ)間動(dòng)畫”),這種動(dòng)畫的好處就是開(kāi)發(fā)者不用逐個(gè)控制每個(gè)動(dòng)畫幀颁独,而只要關(guān)心幾個(gè)關(guān)鍵幀的狀態(tài)即可彩届。
關(guān)鍵幀動(dòng)畫開(kāi)發(fā)分為兩種形式:一種是通過(guò)設(shè)置不同的屬性值進(jìn)行關(guān)鍵幀控制,另一種是通過(guò)繪制路徑進(jìn)行關(guān)鍵幀控制誓酒。后者優(yōu)先級(jí)高于前者樟蠕,如果設(shè)置了路徑則屬性值就不再起作用。
對(duì)于前面的落花動(dòng)畫效果而言其實(shí)落花的過(guò)程并不自然靠柑,很顯然實(shí)際生活中它不可能沿著直線下落寨辩,這里我們不妨通過(guò)關(guān)鍵幀動(dòng)畫的values屬性控制它在下落過(guò)程中的屬性。假設(shè)下落過(guò)程如圖:
在這里需要設(shè)置四個(gè)關(guān)鍵幀(如圖中四個(gè)關(guān)鍵點(diǎn))歼冰,具體代碼如下(動(dòng)畫創(chuàng)建過(guò)程同基本動(dòng)畫基本完全一致):
運(yùn)行效果(注意運(yùn)行結(jié)束沒(méi)有設(shè)置圖層位置為動(dòng)畫運(yùn)動(dòng)結(jié)束位置):
上面的方式固然比前面使用基礎(chǔ)動(dòng)畫效果要好一些靡狞,但其實(shí)還是存在問(wèn)題,那就是落花飛落的路徑是直線的隔嫡,當(dāng)然這個(gè)直線是根據(jù)程序中設(shè)置的四個(gè)關(guān)鍵幀自動(dòng)形成的甸怕,那么如何讓它沿著曲線飄落呢?這就是第二種類型的關(guān)鍵幀動(dòng)畫腮恩,通過(guò)描繪路徑進(jìn)行關(guān)鍵幀動(dòng)畫控制梢杭。假設(shè)讓落花沿著下面的曲線路徑飄落:
當(dāng)然,這是一條貝塞爾曲線秸滴,學(xué)習(xí)了前篇文章之后相信對(duì)于這類曲線應(yīng)該并不陌生武契,下面是具體實(shí)現(xiàn)代碼:
運(yùn)行效果(注意運(yùn)行結(jié)束沒(méi)有設(shè)置圖層位置為動(dòng)畫運(yùn)動(dòng)結(jié)束位置):
2.3 動(dòng)畫組
實(shí)際開(kāi)發(fā)中一個(gè)物體的運(yùn)動(dòng)往往是復(fù)合運(yùn)動(dòng),單一屬性的運(yùn)動(dòng)情況比較少荡含,但恰恰屬性動(dòng)畫每次進(jìn)行動(dòng)畫設(shè)置時(shí)一次只能設(shè)置一個(gè)屬性進(jìn)行動(dòng)畫控制(不管是基礎(chǔ)動(dòng)畫還是關(guān)鍵幀動(dòng)畫都是如此)咒唆,這樣一來(lái)要做一個(gè)復(fù)合運(yùn)動(dòng)的動(dòng)畫就必須創(chuàng)建多個(gè)屬性動(dòng)畫進(jìn)行組合。對(duì)于一兩種動(dòng)畫的組合或許處理起來(lái)還比較容易内颗,但是對(duì)于更多動(dòng)畫的組合控制往往會(huì)變得很麻煩钧排,動(dòng)畫組的產(chǎn)生就是基于這樣一種情況而產(chǎn)生的。動(dòng)畫組是一系列動(dòng)畫的組合均澳,凡是添加到動(dòng)畫組中的動(dòng)畫都受控于動(dòng)畫組恨溜,這樣一來(lái)各類動(dòng)畫公共的行為就可以統(tǒng)一進(jìn)行控制而不必單獨(dú)設(shè)置符衔,而且放到動(dòng)畫組中的各個(gè)動(dòng)畫可以并發(fā)執(zhí)行,共同構(gòu)建出復(fù)雜的動(dòng)畫效果糟袁。
動(dòng)畫組使用起來(lái)并不復(fù)雜判族,首先單獨(dú)創(chuàng)建單個(gè)動(dòng)畫(可以是基礎(chǔ)動(dòng)畫也可以是關(guān)鍵幀動(dòng)畫),然后將基礎(chǔ)動(dòng)畫添加到動(dòng)畫組项戴,最后將動(dòng)畫組添加到圖層即可形帮。
前面關(guān)鍵幀動(dòng)畫部分,路徑動(dòng)畫看起來(lái)效果雖然很流暢周叮,但是落花本身的旋轉(zhuǎn)運(yùn)動(dòng)沒(méi)有了辩撑,這里不妨將基礎(chǔ)動(dòng)畫部分的旋轉(zhuǎn)動(dòng)畫和路徑關(guān)鍵幀動(dòng)畫進(jìn)行組合使得整個(gè)動(dòng)畫看起來(lái)更加的和諧、順暢仿耽。
運(yùn)行效果:
2.4 轉(zhuǎn)場(chǎng)動(dòng)畫
轉(zhuǎn)場(chǎng)動(dòng)畫就是從一個(gè)場(chǎng)景以動(dòng)畫的形式過(guò)渡到另一個(gè)場(chǎng)景合冀。轉(zhuǎn)場(chǎng)動(dòng)畫的使用一般分為以下幾個(gè)步驟:
1.創(chuàng)建轉(zhuǎn)場(chǎng)動(dòng)畫
2.設(shè)置轉(zhuǎn)場(chǎng)類型、子類型(可選)及其他屬性
3.設(shè)置轉(zhuǎn)場(chǎng)后的新視圖并添加動(dòng)畫到圖層
下表列出了常用的轉(zhuǎn)場(chǎng)類型(注意私有API是蘋果官方?jīng)]有公開(kāi)的動(dòng)畫類型项贺,但是目前通過(guò)仍然可以使用):
在前面的文章“IOS開(kāi)發(fā)系列--無(wú)限循環(huán)的圖片瀏覽器”中為了使用UIScrollView做無(wú)限循環(huán)圖片瀏覽器花費(fèi)了不少時(shí)間在性能優(yōu)化上面君躺,這里使用轉(zhuǎn)場(chǎng)動(dòng)畫利用一個(gè)UIImageView實(shí)現(xiàn)一個(gè)漂亮的無(wú)限循環(huán)圖片瀏覽器。
運(yùn)行效果:
代碼十分簡(jiǎn)單开缎,但是效果和性能卻很驚人棕叫。當(dāng)然演示代碼有限,其他動(dòng)畫類型大家可以自己實(shí)現(xiàn)奕删,效果都很絢麗俺泣。
2.5逐幀動(dòng)畫
前面介紹了核心動(dòng)畫中大部分動(dòng)畫類型,但是做過(guò)動(dòng)畫處理的朋友都知道急侥,在動(dòng)畫制作中還有一種動(dòng)畫類型“逐幀動(dòng)畫”砌滞。說(shuō)到逐幀動(dòng)畫相信很多朋友第一個(gè)想到的就是UIImageView侮邀,通過(guò)設(shè)置UIImageView的animationImages屬性坏怪,然后調(diào)用它的startAnimating方法去播放這組圖片。當(dāng)然這種方法在某些場(chǎng)景下是可以達(dá)到逐幀的動(dòng)畫效果绊茧,但是它也存在著很大的性能問(wèn)題铝宵,并且這種方法一旦設(shè)置完圖片中間的過(guò)程就無(wú)法控制了。當(dāng)然华畏,也許有朋友會(huì)想到利用iOS的定時(shí)器NSTimer定時(shí)更新圖片來(lái)達(dá)到逐幀動(dòng)畫的效果鹏秋。這種方式確實(shí)可以解決UIImageView一次性加載大量圖片的問(wèn)題,而且讓播放過(guò)程可控亡笑,唯一的缺點(diǎn)就是定時(shí)器方法調(diào)用有時(shí)可能會(huì)因?yàn)楫?dāng)前系統(tǒng)執(zhí)行某種比較占用時(shí)間的任務(wù)造成動(dòng)畫連續(xù)性出現(xiàn)問(wèn)題侣夷。
注意:上面僅僅演示了逐幀動(dòng)畫的過(guò)程,事實(shí)上結(jié)合其他動(dòng)畫類型可以讓整條魚(yú)游動(dòng)起來(lái)仑乌,這里不再贅述百拓。
3 UIView動(dòng)畫封裝
有了前面核心動(dòng)畫的知識(shí)琴锭,相信大家開(kāi)發(fā)出一般的動(dòng)畫效果應(yīng)該不在話下。在核心動(dòng)畫開(kāi)篇也給大家說(shuō)過(guò)衙传,其實(shí)UIView本身對(duì)于基本動(dòng)畫和關(guān)鍵幀動(dòng)畫决帖、轉(zhuǎn)場(chǎng)動(dòng)畫都有相應(yīng)的封裝,在對(duì)動(dòng)畫細(xì)節(jié)沒(méi)有特殊要求的情況下使用起來(lái)也要簡(jiǎn)單的多蓖捶〉鼗兀可以說(shuō)在日常開(kāi)發(fā)中90%以上的情況使用UIView的動(dòng)畫封裝方法都可以搞定,因此在熟悉了核心動(dòng)畫的原理之后還是有必要給大家簡(jiǎn)單介紹一下UIView中各類動(dòng)畫使用方法的俊鱼。由于前面核心動(dòng)畫內(nèi)容已經(jīng)進(jìn)行過(guò)詳細(xì)介紹刻像,學(xué)習(xí)UIView的封裝方法根本是小菜一碟,這里對(duì)于一些細(xì)節(jié)就不再贅述了并闲。
基礎(chǔ)動(dòng)畫
基礎(chǔ)動(dòng)畫部分和前面的基礎(chǔ)動(dòng)畫演示相對(duì)應(yīng)绎速,演示點(diǎn)擊屏幕落葉飄落到鼠標(biāo)點(diǎn)擊位置的過(guò)程。注意根據(jù)前面介紹的隱式動(dòng)畫知識(shí)其實(shí)非根圖層直接設(shè)置終點(diǎn)位置不需要使用UIView的動(dòng)畫方法也可以實(shí)現(xiàn)動(dòng)畫效果焙蚓,因此這里落花不再放到圖層中而是放到了一個(gè)UIImageView中纹冤。
下面的代碼演示了通過(guò)block和靜態(tài)方法實(shí)現(xiàn)動(dòng)畫控制的過(guò)程:
補(bǔ)充--彈簧動(dòng)畫效果
由于在iOS開(kāi)發(fā)中彈性動(dòng)畫使用很普遍,所以在iOS7蘋果官方直接提供了一個(gè)方法用于彈性動(dòng)畫開(kāi)發(fā)购公,下面簡(jiǎn)單的演示一下:
運(yùn)行效果:
補(bǔ)充--動(dòng)畫設(shè)置參數(shù)
在動(dòng)畫方法中有一個(gè)option參數(shù)萌京,UIViewAnimationOptions類型,它是一個(gè)枚舉類型宏浩,動(dòng)畫參數(shù)分為三類知残,可以組合使用:
1.常規(guī)動(dòng)畫屬性設(shè)置(可以同時(shí)選擇多個(gè)進(jìn)行設(shè)置)
UIViewAnimationOptionLayoutSubviews:動(dòng)畫過(guò)程中保證子視圖跟隨運(yùn)動(dòng)。
UIViewAnimationOptionAllowUserInteraction:動(dòng)畫過(guò)程中允許用戶交互比庄。
UIViewAnimationOptionBeginFromCurrentState:所有視圖從當(dāng)前狀態(tài)開(kāi)始運(yùn)行求妹。
UIViewAnimationOptionRepeat:重復(fù)運(yùn)行動(dòng)畫。
UIViewAnimationOptionAutoreverse :動(dòng)畫運(yùn)行到結(jié)束點(diǎn)后仍然以動(dòng)畫方式回到初始點(diǎn)佳窑。
UIViewAnimationOptionOverrideInheritedDuration:忽略嵌套動(dòng)畫時(shí)間設(shè)置制恍。
UIViewAnimationOptionOverrideInheritedCurve:忽略嵌套動(dòng)畫速度設(shè)置。
UIViewAnimationOptionAllowAnimatedContent:動(dòng)畫過(guò)程中重繪視圖(注意僅僅適用于轉(zhuǎn)場(chǎng)動(dòng)畫)神凑。
UIViewAnimationOptionShowHideTransitionViews:視圖切換時(shí)直接隱藏舊視圖净神、顯示新視圖,而不是將舊視圖從父視圖移除(僅僅適用于轉(zhuǎn)場(chǎng)動(dòng)畫)
UIViewAnimationOptionOverrideInheritedOptions :不繼承父動(dòng)畫設(shè)置或動(dòng)畫類型溉委。
2.動(dòng)畫速度控制(可從其中選擇一個(gè)設(shè)置)
UIViewAnimationOptionCurveEaseInOut:動(dòng)畫先緩慢鹃唯,然后逐漸加速。
UIViewAnimationOptionCurveEaseIn :動(dòng)畫逐漸變慢瓣喊。
UIViewAnimationOptionCurveEaseOut:動(dòng)畫逐漸加速坡慌。
UIViewAnimationOptionCurveLinear :動(dòng)畫勻速執(zhí)行,默認(rèn)值藻三。
3.轉(zhuǎn)場(chǎng)類型(僅適用于轉(zhuǎn)場(chǎng)動(dòng)畫設(shè)置洪橘,可以從中選擇一個(gè)進(jìn)行設(shè)置絮爷,基本動(dòng)畫、關(guān)鍵幀動(dòng)畫不需要設(shè)置)
UIViewAnimationOptionTransitionNone:沒(méi)有轉(zhuǎn)場(chǎng)動(dòng)畫效果梨树。
UIViewAnimationOptionTransitionFlipFromLeft :從左側(cè)翻轉(zhuǎn)效果坑夯。
UIViewAnimationOptionTransitionFlipFromRight:從右側(cè)翻轉(zhuǎn)效果。
UIViewAnimationOptionTransitionCurlUp:向后翻頁(yè)的動(dòng)畫過(guò)渡效果抡四。
UIViewAnimationOptionTransitionCurlDown :向前翻頁(yè)的動(dòng)畫過(guò)渡效果柜蜈。
UIViewAnimationOptionTransitionCrossDissolve:舊視圖溶解消失顯示下一個(gè)新視圖的效果。
UIViewAnimationOptionTransitionFlipFromTop :從上方翻轉(zhuǎn)效果指巡。
UIViewAnimationOptionTransitionFlipFromBottom:從底部翻轉(zhuǎn)效果淑履。
關(guān)鍵幀動(dòng)畫
從iOS7開(kāi)始UIView動(dòng)畫中封裝了關(guān)鍵幀動(dòng)畫,下面就來(lái)看一下如何使用UIView封裝方法進(jìn)行關(guān)鍵幀動(dòng)畫控制藻雪,這里實(shí)現(xiàn)前面關(guān)鍵幀動(dòng)畫部分對(duì)于落花的控制秘噪。
補(bǔ)充--動(dòng)畫設(shè)置參數(shù)
對(duì)于關(guān)鍵幀動(dòng)畫也有一些動(dòng)畫參數(shù)設(shè)置options,UIViewKeyframeAnimationOptions類型勉耀,和上面基本動(dòng)畫參數(shù)設(shè)置有些差別指煎,關(guān)鍵幀動(dòng)畫設(shè)置參數(shù)分為兩類,可以組合使用:
1.常規(guī)動(dòng)畫屬性設(shè)置(可以同時(shí)選擇多個(gè)進(jìn)行設(shè)置)
UIViewAnimationOptionLayoutSubviews:動(dòng)畫過(guò)程中保證子視圖跟隨運(yùn)動(dòng)便斥。
UIViewAnimationOptionAllowUserInteraction:動(dòng)畫過(guò)程中允許用戶交互至壤。
UIViewAnimationOptionBeginFromCurrentState:所有視圖從當(dāng)前狀態(tài)開(kāi)始運(yùn)行。
UIViewAnimationOptionRepeat:重復(fù)運(yùn)行動(dòng)畫枢纠。
UIViewAnimationOptionAutoreverse :動(dòng)畫運(yùn)行到結(jié)束點(diǎn)后仍然以動(dòng)畫方式回到初始點(diǎn)像街。
UIViewAnimationOptionOverrideInheritedDuration:忽略嵌套動(dòng)畫時(shí)間設(shè)置。
UIViewAnimationOptionOverrideInheritedOptions :不繼承父動(dòng)畫設(shè)置或動(dòng)畫類型晋渺。
2.動(dòng)畫模式設(shè)置(同前面關(guān)鍵幀動(dòng)畫動(dòng)畫模式一一對(duì)應(yīng)镰绎,可以從其中選擇一個(gè)進(jìn)行設(shè)置)
UIViewKeyframeAnimationOptionCalculationModeLinear:連續(xù)運(yùn)算模式。
UIViewKeyframeAnimationOptionCalculationModeDiscrete :離散運(yùn)算模式木西。
UIViewKeyframeAnimationOptionCalculationModePaced:均勻執(zhí)行運(yùn)算模式畴栖。
UIViewKeyframeAnimationOptionCalculationModeCubic:平滑運(yùn)算模式。
UIViewKeyframeAnimationOptionCalculationModeCubicPaced:平滑均勻運(yùn)算模式户魏。
注意:前面說(shuō)過(guò)關(guān)鍵幀動(dòng)畫有兩種形式驶臊,上面演示的是屬性值關(guān)鍵幀動(dòng)畫,路徑關(guān)鍵幀動(dòng)畫目前UIView還不支持叼丑。
轉(zhuǎn)場(chǎng)動(dòng)畫
從iOS4.0開(kāi)始,UIView直接封裝了轉(zhuǎn)場(chǎng)動(dòng)畫扛门,使用起來(lái)同樣很簡(jiǎn)單鸠信。
上面的轉(zhuǎn)場(chǎng)動(dòng)畫演示中,其實(shí)僅僅有一個(gè)視圖UIImageView做轉(zhuǎn)場(chǎng)動(dòng)畫论寨,每次轉(zhuǎn)場(chǎng)通過(guò)切換UIImageView的內(nèi)容而已星立。如果有兩個(gè)完全不同的視圖爽茴,并且每個(gè)視圖布局都很復(fù)雜,此時(shí)要在這兩個(gè)視圖之間進(jìn)行轉(zhuǎn)場(chǎng)可以使用+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^)(BOOL finished))completion NS_AVAILABLE_IOS(4_0)方法進(jìn)行兩個(gè)視圖間的轉(zhuǎn)場(chǎng)绰垂,需要注意的是默認(rèn)情況下轉(zhuǎn)出的視圖會(huì)從父視圖移除室奏,轉(zhuǎn)入后重新添加,可以通過(guò)UIViewAnimationOptionShowHideTransitionViews參數(shù)設(shè)置劲装,設(shè)置此參數(shù)后轉(zhuǎn)出的視圖會(huì)隱藏(不會(huì)移除)轉(zhuǎn)入后再顯示胧沫。
注意:轉(zhuǎn)場(chǎng)動(dòng)畫設(shè)置參數(shù)完全同基本動(dòng)畫參數(shù)設(shè)置;同直接使用轉(zhuǎn)場(chǎng)動(dòng)畫不同的是使用UIView的裝飾方法進(jìn)行轉(zhuǎn)場(chǎng)動(dòng)畫其動(dòng)畫效果較少占业,因?yàn)檫@里無(wú)法直接使用私有API绒怨。
轉(zhuǎn)載請(qǐng)注明原文鏈接:http://www.cnblogs.com/kenshincui/p/3972100.html#autoid-3-2-0