天天看點

iOS開發CoreAnimation解讀之四——Layer層動畫内容

        通過前幾篇部落格的介紹,我們可以了解到layer層可以設定許多與控件ui相關的屬性,并且對于ios開發,uiview層的屬性是會映射到calayer的,是以,可以通過uikit和coreanimation兩個架構來設定控件的ui相關屬性,當屬性發生變化時,我們可以使其展示一個動畫效果。

        caanimation是coreanimation架構中執行動畫對象的基類,下面有一張圖,是我手畫的,不太美觀,但是可以将與caanimation相關的幾個動畫類的關系表達清楚:

iOS開發CoreAnimation解讀之四——Layer層動畫内容

從上圖中可以看到,從caanimation中繼承出三個子類,分别是用于建立屬性動畫的capropertyanimation,建立轉場動畫的catransition和建立組合動畫的caanimationgroup。

我們就先從根類開始探讨。

caanimation作為動畫對象的基類,其中封裝了動畫的基礎屬性,如下:

<a href="http://my.oschina.net/u/2340880/blog/539599#">?</a>

1

2

3

4

5

6

7

8

<code>//通過類方法建立一個caanimation對象</code>

<code>+ (instancetype)animation;</code>

<code>//動畫執行的時序模式</code>

<code>@property(nullable, strong) camediatimingfunction *timingfunction;</code>

<code>//代理</code>

<code>@property(nullable, strong) id delegate;</code>

<code>//是否動畫完成時将動畫對象移除掉</code>

<code>@property(getter=isremovedoncompletion) </code><code>bool</code> <code>removedoncompletion;</code>

timingfunction定義了動畫執行的時序效果,camediatimingfunction的建立方式如下:

9

10

11

12

13

14

<code>/*</code>

<code>name參數決定的執行的效果,可選參數如下</code>

<code>//線性執行</code>

<code> </code><code>nsstring * const kcamediatimingfunctionlinear;</code>

<code> </code><code>//淡入  在動畫開始時 淡入效果</code>

<code> </code><code>nsstring * const kcamediatimingfunctioneasein;</code>

<code> </code><code>//淡出 在動畫結束時 淡出效果</code>

<code> </code><code>nsstring * const kcamediatimingfunctioneaseout;</code>

<code> </code><code>//淡入淡出</code>

<code> </code><code>nsstring * const kcamediatimingfunctioneaseineaseout;</code>

<code> </code><code>//預設效果</code>

<code> </code><code>nsstring * const kcamediatimingfunctiondefault;</code>

<code>*/</code>

<code>+ (instancetype)functionwithname:(nsstring *)name;</code>

caanimation的代理方法入如下幾個:

<code>//動畫開始時執行的回調</code>

<code>- (</code><code>void</code><code>)animationdidstart:(caanimation *)anim;</code>

<code>//動畫結束後執行的回調</code>

<code>- (</code><code>void</code><code>)animationdidstop:(caanimation *)anim finished:(</code><code>bool</code><code>)flag;</code>

        capropertyanimation是繼承于caanimation專門用來建立與屬性相關的動畫的類:

<code>//建立對象 參數中的path就是我們要執行動畫的屬性</code>

<code>//例如,如果傳入@"backgroundcolor" 當layer的背景顔色改變時,就會執行我們設定的動畫</code>

<code>+ (instancetype)animationwithkeypath:(nullable nsstring *)path;</code>

<code>//這個屬性确定動畫執行的狀态是否疊加在控件的原狀态上</code>

<code>//預設設定為no,如果我們執行兩次位置移動的動畫,會從同一位置執行兩次</code>

<code>//如果設定為yes,則會在第一次執行的基礎上執行第二次動畫</code>

<code>@property(getter=isadditive) </code><code>bool</code> <code>additive;</code>

<code>//這個屬性對重複執行的動畫有效果</code>

<code>//預設為no,重複執行的動畫每次都是從起始狀态開始</code>

<code>//如果設定為yes,則為此執行都會在上一次執行的基礎上執行</code>

<code>@property(getter=iscumulative) </code><code>bool</code> <code>cumulative;</code>

<code>//這個屬性和transfron屬性的動畫執行相關</code>

<code>@property(nullable, strong) cavaluefunction *valuefunction;</code>

上面這些屬性中,隻有一個需要我們注意,valuefunction是專門為了transform動畫而設定的,因為我們沒有辦法直接改變transform3d中的屬性,通過這個參數,可以幫助我們直接操作transfrom3d屬性變化産生動畫效果,舉例如下,一個繞z軸旋轉的動畫:

<code> </code><code>//繞z軸旋轉的動畫</code>

<code>    </code><code>cabasicanimation * ani = [cabasicanimation animationwithkeypath:@</code><code>"transform"</code><code>];</code>

<code>    </code><code>//從0度開始</code>

<code>    </code><code>ani.fromvalue = @0;</code>

<code>    </code><code>//旋轉到180度</code>

<code>    </code><code>ani.tovalue = [nsnumber numberwithfloat:m_pi];</code>

<code>    </code><code>//時間2s</code>

<code>    </code><code>ani.duration = 2;</code>

<code>    </code><code>//設定為z軸旋轉</code>

<code>    </code><code>ani.valuefunction = [cavaluefunction functionwithname:kcavaluefunctionrotatez];</code>

<code>    </code><code>//執行動畫</code>

<code>    </code><code>[layer addanimation:ani forkey:@</code><code>""</code><code>];</code>

實際上,使用點的方式也是可以通路到相應屬性的,如果不設定valuefunction,使用如下方法也是可以進行繞z軸旋轉的:

<code>//繞z軸旋轉的動畫</code>

<code>    </code><code>cabasicanimation * ani = [cabasicanimation animationwithkeypath:@</code><code>"transform.rotation.z"</code><code>];</code>

        cabasicanimaton是capropertyanimation分出來的一個子類,建立基礎的屬性變化動畫,例如我們上面的示例代碼,其中屬性如下:

<code>@property(nullable, strong) id fromvalue;</code>

<code>@property(nullable, strong) id tovalue;</code>

<code>@property(nullable, strong) id byvalue;</code>

上面三個屬性都是來确定動畫的起始與結束位置,有如下的含義:

fromvalue和tovalue不為空:動畫的值由fromvalue變化到tovalue

fromvalue和byvalue不為空:動畫的值由fromvalue變化到fromvalue+byvalue

byvalue和tovalue不為空:動畫的值由tovalue-byvalue變化到tovalue

隻有fromvalue不為空:動畫的值由fromvalue變化到layer的目前狀态值

隻有tovalue不為空:動畫的值由layer目前的值變化到tovalue

隻有byvalue不為空:動畫的值由layer目前的值變化到layer目前的值+byvalue

        cakeyframeanimation也是繼承與capropertyanimation的一個子類,其與cabasicanimation的不同之處在于雖然其都是改變layer層屬性的動畫,但是cabasicanimation隻能設定初始與結束狀态,這之間我們沒辦法控制,而cakeyframeanimation可以讓我們設定一些關鍵幀再整個動畫的過程中。屬性方法如下:

15

16

17

<code>//關鍵幀的值數組 例如我們想讓控件沿某個路徑移動,這裡面存放每個移動的點</code>

<code>@property(nullable, copy) nsarray *values;</code>

<code>//直接設定路徑,作用域values類似</code>

<code>@property(nullable) cgpathref path;</code>

<code>//設定每一幀執行的時間長短 這個的取值為0-1,代表占用時間的比例</code>

<code>@property(nullable, copy) nsarray&lt;nsnumber *&gt; *keytimes;</code>

<code>//每一幀執行過程中的時序效果 上面有提過</code>

<code>@property(nullable, copy) nsarray&lt;camediatimingfunction *&gt; *timingfunctions;</code>

<code>設定幀的中間值如何計算</code>

<code> </code><code>nsstring * const kcaanimationlinear;</code>

<code> </code><code>nsstring * const kcaanimationdiscrete;</code>

<code> </code><code>nsstring * const kcaanimationpaced;</code>

<code> </code><code>nsstring * const kcaanimationcubic;</code>

<code> </code><code>nsstring * const kcaanimationcubicpaced;</code>

<code>@property(copy) nsstring *calculationmode;</code>

示例如下:

<code>    </code><code>cakeyframeanimation * ani = [cakeyframeanimation animationwithkeypath:@</code><code>"position"</code><code>];</code>

<code>    </code><code>ani.values = @[[nsvalue valuewithcgpoint:cgpointmake(100, 100)],[nsvalue valuewithcgpoint:cgpointmake(120, 100)],[nsvalue valuewithcgpoint:cgpointmake(120, 200)],[nsvalue valuewithcgpoint:cgpointmake(200, 200)]];</code>

<code>    </code><code>ani.duration = 3;</code>

        通過caspringanimation,可以幫助開發者很輕松的建立出有彈簧效果的動畫,主要屬性如下:

<code>//這個屬性設定彈簧重物的品質 會影響慣性 必須大于0 預設為1</code>

<code>@property cgfloat mass;</code>

<code>//設定彈簧的剛度系數,必須大于0 預設為100  這個越大 則回彈越快</code>

<code>@property cgfloat stiffness;</code>

<code>//阻尼系數 預設為10 必須大于0 這個值越大 回彈的幅度越小</code>

<code>@property cgfloat damping;</code>

<code>//初始速度</code>

<code>@property cgfloat initialvelocity;</code>

<code>//擷取動畫停下來需要的時間</code>

<code>@property(readonly) cftimeinterval settlingduration;</code>

        catransition和capropertyanimation的不同之處在于當layer層出現時,會産生動畫效果,而并不是屬性改變時,屬性如下:

18

19

20

21

22

23

24

<code>設定動畫類型</code>

<code>//淡入</code>

<code> </code><code>nsstring * const kcatransitionfade;</code>

<code> </code><code>//移入</code>

<code> </code><code>nsstring * const kcatransitionmovein;</code>

<code> </code><code>//壓入</code>

<code> </code><code>nsstring * const kcatransitionpush;</code>

<code> </code><code>//溶解</code>

<code> </code><code>nsstring * const kcatransitionreveal;</code>

<code>@property(copy) nsstring *type;</code>

<code>設定動畫的方向</code>

<code>//從右側進</code>

<code> </code><code>nsstring * const kcatransitionfromright;</code>

<code> </code><code>//從左側進</code>

<code> </code><code>nsstring * const kcatransitionfromleft;</code>

<code> </code><code>//從上側進</code>

<code> </code><code>nsstring * const kcatransitionfromtop;</code>

<code> </code><code>//從下側進</code>

<code> </code><code>nsstring * const kcatransitionfrombottom;</code>

<code>@property(nullable, copy) nsstring *subtype;</code>

其實,關于type定義的動畫效果,出來官方定義的,我們還可以使用一些私有的參數,如下:

<code>pagecurl   翻頁</code>

<code>rippleeffect 滴水效果</code>

<code>suckeffect 收縮效果,如一塊布被抽走</code>

<code>cube 立方體效果</code>

<code>oglflip 上下翻轉效果</code>

例如:

<code>    </code><code>catransition * ani = [catransition animation];</code>

<code>    </code><code>ani.type =  @</code><code>"pagecurl"</code><code>;</code>

<code>    </code><code>ani.subtype = kcatransitionfromright;</code>

        caanimationgroup本身并沒有定義動畫,他可以将我們上面提到的相關動畫進行組合:

<code>@property(nullable, copy) nsarray&lt;caanimation *&gt; *animations;</code>

<code></code>

繼續閱讀