標籤:
今天說一下有關動畫的基礎,希望能協助到一些剛接觸iOS動畫或者剛開始學習iOS的同學,如有異議,希望能指正,謝謝。 一、一些基礎的概念 下面介紹的都是QuartzCore架構下的內容。 1、CAMediaTimingFunction 時間函數(也被稱為緩衝函數),用來描述動畫過程中運動的速率情況,也可以看成加速度,apple提供的四種方式: kCAMediaTimingFunctionLinear 勻速 kCAMediaTimingFunctionEaseIn 慢入 kCAMediaTimingFunctionEaseOut 慢出 kCAMediaTimingFunctionEaseInEaseOut 慢入慢出 kCAMediaTimingFunctionDefault 預設 上面的四種情況可以用來表示: 當然,除了給我們提供的方式,我們還可以自訂時間函數,通過+functionWithControlPoints::::方法。 這個方式是傳入兩個點(control point)(前兩個是一個點,後兩個是一個點)。第一個點與原點形成第一個切線,第二個點與(1,1)點形成另一個切線,比如說傳入的點為(1,0)和(0.75,1),則它的速率(加速度)對應的圖形: 這樣就可以自訂你想要的時間函數。 2、CAMediaTiming 這是一個protocol,被CALayer和CAAnimation遵守,它是一個分級定時系統,描述一個對象相對於父物件到當地時間的映射(有點繞,這句應該怎麼翻譯,請大神指教:The
CAMediaTiming protocol models a hierarchical timing system, with each object describing the mapping of time values from the object‘s parent to local time.)。主要是用來描述動畫中的開始、執行時間,執行速率,重複次數等。 3、CFTimeInterval 表示時間間隔,就是double類型,起的別名 4、CATransaction 文檔中這樣描述的:“Transactions是CoreAnimation批量處理layer-tree去原子的更新渲染的機制,每一個layer tree 的改變都需要transaction這一個部分。CoreAnimation支援兩種transactions,“顯示”transaction和“隱式”transaction。”顯示的transaction是在改變layer tree之前調用[CATransaction begin],然後[CATransaction commit]。隱式的transaction是當沒有活躍的transaction的layer tree 在一個線程中被修改時,CoreAnimation自動的建立的transaction,這些transactions在runLoop的下一次迭代中被自動commit,在一些特殊的情況下(比如說沒有runLoop或者runLoop被阻塞了),就必須用顯示的transaction在合適的時機去渲染layer tree的跟新。”,我相信文檔中的描述已經很清晰的說明了CATransaction是幹什麼,怎麼工作的了。下面舉一個例子,在例子中進行簡單的說明,先看一下:
這個是一個簡單的修改layer的的屬性形成的動畫,layer的很多屬性都是支援隱式動畫的,你只需要修改他的屬性,它就會自動的加入一個動畫的效果。上面的效果,代碼如下: 很簡單的代碼,只是再點擊button的時候修改layer的position和backgroundColor。這屬於上面提到的隱式transaction,如果改成顯示動畫是這樣寫的, 可能你會覺得,這樣寫的結果跟上面的結果一樣的,沒辦法判斷到底是不是顯示的動畫,你可以去掉下面的commit這一行的代碼,運行一下,就會發現,並沒有執行動畫,這就是上面文檔中提到的,commit的操作是講一系列的事務(transactions)提交,等待下個runLoop時渲染。你還可以通過設定CATransaction來修改動畫的時間,和之前學習的CAMediaTimingFunction,代碼如下:
當然可以使用+(void)setAnimationDuration:(CFTimeInterval)dur;方法來設定動畫時間,時間函數也可以。
還有一個關閉隱式動畫的方式就是disableAction設定為NO,通過setDisableActions:或者kCATransactionDisableActions都可以。
CATransaction中還提供有setCompletionBlock或者kCATransactionCompletionBlock,使用上面兩種方法可以設定動畫之後的的回調,這個應該還是很好用的,很多動畫之後是需要進行某一個action的。 5、CAAction 這是一個protocol,定義在CALayer的標頭檔中,CAAnimation和CALayer類遵守了這個協議。它有一個方法,是當一個對象發生一個事件,會調用這個方法,參數為這個事件的name,發生事件的對象anObject,儲存這個事件相關的參數dic。 大家都知道UIView是對CALayer的一層封裝,UIView遵守了CALayerDelegate,實現就了協議的方法(具體UIView和CALayer的關係和區別這裡就不過多的描述了),到這裡就會有一個疑問,為什麼CALayer的屬性有隱式動畫,而UIView的layer沒有呢? 我們先從CALayer的方法actionForKey:方法說起,當我們改變CALayer的屬性時,會調用這個方法傳遞屬性名稱: 1、判斷當前delegate對象是否實現了actionForLayer:forKey:方法,如果實現就調用; 2、檢查這個layer的actions字典中是否有當前屬性名稱 3、在“style”層面檢查任何actions字典中是否有當前屬性名稱 4、如果上面所有步驟都沒有找到,那麼就調用預設的defaultActionForKey:方法 註:以上任何一步返回非nil action對象都會被忽略(不做任何操作) 所以,我們可以自訂一個UIView,然後重寫父類的actionForLayer:forKey:方法,返回nil,就可以讓一個UIView也有隱式動畫了,趕緊試試吧。 那隱式動畫到底是怎樣實現的呢?下面我們繼續看看CALayer做了什麼,我們給自訂的UIView自訂一個Layer,layer中有添加和移除animation的方法,我們在自訂的CALayer重寫addAnimation:forKey:方法,當點擊button,改變layer的屬性時,效果如:從結果看出,隱式動畫也是給當前的layer加上了動畫效果的。 下面再做一個實驗,剛在自訂的UIView中重寫的actionForLayer:forKey方法中直接返回的nil,然後對自訂view的layer做隱式動畫的效果是:
可以從中看出,再自訂view中的actionforlayer方法被調用之後就給layer加入了動畫。當你在actionForLayer:forKey:方法中加入判斷:
這樣修改position的隱式動畫就沒有了,只有對backgroundColor的動畫。同時也印證了上面提到的4個步驟。
今天就先這麼多,後面再補充。。。。。。(未完,待續)
iOS 動畫基礎