iOS核心動(dòng)畫高級(jí)技巧:第二部分-動(dòng)畫

傳送門:《iOS核心動(dòng)畫高級(jí)技巧》部分源碼

CA利用RunLoop收集圖層 Animatable屬性 的修改(如backgroundColor等)偿衰,并基于事務(wù)對(duì)【隱式動(dòng)畫】進(jìn)行管理;簡單來說隱式動(dòng)畫只能完成部分基礎(chǔ)屬性動(dòng)畫,而【顯式動(dòng)畫】則通過 關(guān)鍵幀動(dòng)畫澜术、動(dòng)畫組 對(duì)屬性動(dòng)畫提供更具體的控制或組合庭再,通過 過渡 支持 NonAnimatable屬性和圖層樹的變化膳汪;而【圖層時(shí)間】介紹了Core Animation用來操作時(shí)間控制動(dòng)畫的機(jī)制:CAMediaTiming協(xié)議和層級(jí)關(guān)系時(shí)間茄袖,并給出了手動(dòng)動(dòng)畫的通用解決方案;【緩沖】通過控制 速度 使動(dòng)畫更平滑更自然雏胃;如果需要實(shí)時(shí)控制動(dòng)畫/更強(qiáng)的交互控制動(dòng)畫请毛,可以使用【基于定時(shí)器的動(dòng)畫】。
 
從結(jié)構(gòu)上來說瞭亮,CAAnimation包括計(jì)時(shí)函數(shù)(CAMediaTimingFunction)方仿、一個(gè)圖層委托(CALayerDelegate,用于反饋動(dòng)畫狀態(tài))和一個(gè)removedOnCompletion(標(biāo)識(shí)動(dòng)畫是否該在結(jié)束后自動(dòng)釋放,默認(rèn)YES ,為了防止內(nèi)存泄露)仙蚜,另外還實(shí)現(xiàn)了以下協(xié)議:
  - CAAction (允許 CAAnimation 的子類提供圖層行為)
  - CAMediaTiming (第九章“圖層時(shí)間”將會(huì)詳細(xì)解釋)此洲。

我發(fā)現(xiàn)一個(gè)很奇怪的問題:使用animation.beginTime有時(shí)導(dǎo)致動(dòng)畫失效、有時(shí)類似無序的timeOffset鳍征,未能實(shí)現(xiàn)延遲開始動(dòng)畫的功能黍翎?面徽?艳丛?


一些常用的緩沖函數(shù):
RBBAnimation
AHEasing

第七章:隱式動(dòng)畫

隱式動(dòng)畫:Core Animation在每個(gè) RunLoop 周期中自動(dòng)開始一次新的事務(wù)(RunLoop是iOS負(fù)責(zé)收集用戶輸入、處理定時(shí)器或者網(wǎng)絡(luò)事件并且重新繪制屏幕的東西)趟紊,即使不顯式調(diào)用[CATransaction begin];開始一次事務(wù)氮双,任何在一次RunLoop循環(huán)中Animatable屬性的改變也會(huì)被集中起來,然后Core Animation根據(jù)圖層行為和事務(wù)設(shè)置(默認(rèn)0.25秒)去不斷更新視圖的這些屬性在屏幕上的狀態(tài)霎匈。

  • 呈現(xiàn)和模型
    • 呈現(xiàn)樹 - 圖層的當(dāng)前位置
      • -presentationLayer
      • 呈現(xiàn)圖層實(shí)際上是模型圖層的復(fù)制戴差,但是它的屬性值代表了在任何指定時(shí)刻當(dāng)前外觀效果。換句話說铛嘱,你可以通過呈現(xiàn)圖層的值來獲取當(dāng)前屏幕上真正顯示出來的值
      • 呈現(xiàn)圖層僅僅當(dāng)圖層首次被提交(就是第一次在屏幕上顯示)的時(shí)候創(chuàng)建暖释,所以在那之前調(diào)用-presentationLayer將會(huì)返回nil。
      • 需要使用呈現(xiàn)圖層的兩種情況:
        • 同步動(dòng)畫 - 如果你在實(shí)現(xiàn)一個(gè)基于定時(shí)器的動(dòng)畫(見第11章“基于定時(shí)器的動(dòng)畫”)墨吓,而不僅僅是基于事務(wù)的動(dòng)畫球匕,這個(gè)時(shí)候準(zhǔn)確地知道在某一時(shí)刻圖層顯示在什么位置就會(huì)對(duì)正確擺放圖層很有用了。
        • 處理用戶交互 - 如果你想讓你做動(dòng)畫的圖層響應(yīng)用戶輸入帖烘,你可以使用-hitTest:方法來判斷指定圖層是否被觸摸亮曹,這時(shí)候?qū)?em>呈現(xiàn)圖層而不是模型圖層調(diào)用-hitTest:會(huì)顯得更有意義,因?yàn)槌尸F(xiàn)圖層代表了用戶當(dāng)前看到的圖層位置秘症,而不是當(dāng)前動(dòng)畫結(jié)束之后的位置照卦。
    • 模型樹 - 圖層將要到達(dá)的位置
      • –modelLayer
      • 當(dāng)設(shè)置CALayer的屬性,實(shí)際上是在定義當(dāng)前事務(wù)結(jié)束之后圖層如何顯示的模型乡摹。

第八章:顯式動(dòng)畫

8.1 CAAnimation體系結(jié)構(gòu)

-(void)applyBasicAnimation:(CABasicAnimation *)animation toLayer:(CALayer *)layer{
  animation.fromValue = [layer.presentationLayer ?: layer valueForKeyPath:animation.keyPath];
 
  // note: this approach will only work if toValue != nil
  [CATransaction begin];
  [CATransaction setDisableActions:YES];
  [layer setValue:animation.toValue forKeyPath:animation.keyPath];
  [CATransaction commit];
 
  [layer addAnimation:animation forKey:nil];
}
        - 在動(dòng)畫之后更新(需結(jié)合KVC和fillMode) - CAAnimationDelegate
-(void)animationDidStop:(CABasicAnimation *)anim finished:(BOOL)flag
{
  // CAAnimation實(shí)現(xiàn)了KVC(鍵-值-編碼)協(xié)議役耕,于是你可以用-setValue:forKey:和-valueForKey:方法來存取屬性。
  // 可以利用它來判斷到底是哪個(gè)圖層的調(diào)用
  // 另外聪廉,為了確保更新屬性更新發(fā)生在動(dòng)畫返回初始狀態(tài)之前蹄葱,還得考慮fillMode!3小图云!
  [CATransaction begin];
  [CATransaction setDisableActions:YES];
  self.colorLayer.backgroundColor = (__bridge CGColorRef)anim.toValue;
  [CATransaction commit];
}
  • 2-CAKeyframeAnimation
    • 虛擬屬性 - transform.rotation
      • Core Animation自動(dòng)通過CAValueFunction計(jì)算的值來更新屬性
      • 我們可以不通過關(guān)鍵幀一步旋轉(zhuǎn)多于180度的動(dòng)畫。
      • 可以用相對(duì)值而不是絕對(duì)值旋轉(zhuǎn)(設(shè)置byValue而不是toValue)邻邮。
      • 可以不用創(chuàng)建CATransform3D竣况,而是使用一個(gè)簡單的數(shù)值來指定角度。
      • 不會(huì)和transform.position或者transform.scale沖突(同樣是使用關(guān)鍵路徑來做獨(dú)立的動(dòng)畫屬性)筒严。
  • 8.1.2 CAAnimationGroup - 動(dòng)畫組
  • 8.1.3 CATransition - 過渡
    • 影響整個(gè)圖層丹泉,可以用來對(duì)圖層的任何內(nèi)容做任何類型的動(dòng)畫情萤,包括子圖層的添加和移除。
kCATransitionFade //平滑的淡入淡出效果
 
kCATransitionPush  //從頂部滑動(dòng)進(jìn)入摹恨,但不像推送動(dòng)畫那樣把老圖層推走
kCATransitionMoveIn //新圖層從邊緣的一側(cè)滑動(dòng)進(jìn)來筋岛,把舊圖層從另一側(cè)推出去的效果
kCATransitionReveal  //把原始的圖層滑動(dòng)出去來顯示新的外觀,而不是把新的圖層滑動(dòng)進(jìn)入
+ [subtype](https://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CATransition_class/index.html#//apple_ref/occ/instp/CATransition/subtype) - kCATransitionFromRight/Top/Left/Bottom
+ 對(duì)指定的圖層一次只能使用一次CATransition
[self.imageView.layer addAnimation:transition forKey:nil];  //使用默認(rèn)鍵 - kCATransition
  • 隱式過渡

    • 對(duì)于你自己創(chuàng)建的圖層晒哄,這意味著對(duì)圖層contents圖片做的改動(dòng)都會(huì)自動(dòng)附上淡入淡出的動(dòng)畫睁宰。
    • 對(duì)于視圖關(guān)聯(lián)的圖層,或者是其他隱式動(dòng)畫的行為寝凌,這個(gè)特性依然是被禁用的
  • 自定義動(dòng)畫

    • UIView的兩個(gè)方法提供了Core Animation的過渡特性
+transitionFromView:toView:duration:options:completion://可能有圖層樹變化
+transitionWithView:duration:options:animations://圖層樹不變
  • CALayer有一個(gè)-renderInContext:方法柒傻,可以通過把它繪制到Core Graphics的上下文中捕獲當(dāng)前內(nèi)容的圖片,然后把這個(gè)截屏視圖置于原始視圖之上较木,遮住真實(shí)視圖的所有變化红符,于是創(chuàng)建了一個(gè)簡單的過渡效果
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, YES, 0.0);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *coverImage = UIGraphicsGetImageFromCurrentImageContext();
  • -renderInContext:捕獲了圖層的圖片和子圖層,但是不能對(duì)子圖層正確地處理變換效果伐债,而且對(duì)視頻和OpenGL內(nèi)容也不起作用预侯。但是用CATransition,或者用私有的截屏方式就沒有這個(gè)限制了峰锁?萎馅??

8.2 在動(dòng)畫過程中取消動(dòng)畫

  • 注意:動(dòng)畫一旦被移除祖今,圖層的外觀就立刻更新到當(dāng)前的模型圖層的值

第九章:圖層時(shí)間

Core Animation是如何跟蹤時(shí)間的

  • CAMediaTiming協(xié)議
  • CALayer和CAAnimation都實(shí)現(xiàn)了這個(gè)協(xié)議校坑,所以動(dòng)畫時(shí)間可以被任意基于一個(gè)圖層或者一段動(dòng)畫的類控制。
  • 層級(jí)關(guān)系時(shí)間
  • 全局時(shí)間和本地時(shí)間
    • 全局時(shí)間 - 設(shè)備休眠時(shí)會(huì)暫停
CFTimeInterval time = CACurrentMediaTime(); // 馬赫時(shí)間:對(duì)動(dòng)畫的時(shí)間測量提供了一個(gè)相對(duì)值
  • 本地時(shí)間
    每個(gè)CALayer和CAAnimation實(shí)例都有自己本地時(shí)間的概念千诬,是根據(jù)父圖層/動(dòng)畫層級(jí)關(guān)系中的beginTime,timeOffsetspeed屬性計(jì)算耍目。下述方法用來同步不同圖層之間有不同的 speed,timeOffsetbeginTime 的動(dòng)畫:
-(CFTimeInterval)convertTime:(CFTimeInterval)t from/toLayer:(CALayer *)l;

第十章:緩沖

使動(dòng)畫移動(dòng)更平滑更自然


第十一章:基于定時(shí)器的動(dòng)畫

允許我們精確地控制一幀一幀展示;iOS按照每秒60次刷新屏幕徐绑,CAAnimation最機(jī)智的地方在于每次刷新需要展示的時(shí)候去計(jì)算插值和緩沖邪驮。

  • 定時(shí)幀
  • NSTimer
    受RunLoop中的任務(wù)列表影響,可能會(huì)有很大的延遲
    優(yōu)化:
    • 我們可以用CADisplayLink讓更新頻率嚴(yán)格控制在每次屏幕刷新之后傲茄。
    • 基于真實(shí)幀的持續(xù)時(shí)間而不是假設(shè)的更新頻率來做動(dòng)畫毅访。
    • 調(diào)整動(dòng)畫計(jì)時(shí)器的run loop模式,這樣就不會(huì)被別的事件干擾盘榨。
  • CADisplayLink
    • 不能保證每一幀都按計(jì)劃執(zhí)行喻粹,一些失去控制的離散的任務(wù)或者事件(例如資源緊張的后臺(tái)程序)可能會(huì)導(dǎo)致動(dòng)畫偶爾地丟幀。當(dāng)使用NSTimer的時(shí)候草巡,一旦有機(jī)會(huì)計(jì)時(shí)器就會(huì)開啟守呜,但是CADisplayLink卻不一樣:如果它丟失了幀,就會(huì)直接忽略它們,然后在下一次更新的時(shí)候接著運(yùn)行查乒。
    • 計(jì)算幀的持續(xù)時(shí)間
      然后根據(jù)緩沖函數(shù)計(jì)算下一幀的目標(biāo)位置弥喉,達(dá)到精確控制、動(dòng)畫平滑
  • 物理模擬
    • Chipmunk
      • 基礎(chǔ)類
      • cpSpace - 所有的物理結(jié)構(gòu)體的容器 (一個(gè)大小和一個(gè)可選的重力矢量)
      • cpBody - 固態(tài)無彈力的剛體 (坐標(biāo)+其他物理屬性玛迄,例如質(zhì)量由境,運(yùn)動(dòng)和摩擦系數(shù)等等)
      • cpShape - 抽象的幾何形狀,有各種子類代表不同形狀 (比如cpPolyShape)蓖议,可以給結(jié)構(gòu)體添加一個(gè)多邊形用來檢測碰撞虏杰。
      • 添加用戶交互
        • cpShapeSetCollisionType
        • cpSpaceAddStaticShape
      • 模擬時(shí)間以及固定的時(shí)間步長
        根據(jù)屏幕刷新的時(shí)間跟蹤時(shí)間步長,然后根據(jù)每幀去計(jì)算一個(gè)或者多個(gè)模擬出來的效果拒担。
        • 對(duì)于實(shí)現(xiàn)動(dòng)畫的緩沖效果來說嘹屯,計(jì)算每幀持續(xù)的時(shí)間是一個(gè)很好的解決方案
        • 對(duì)模擬物理效果則應(yīng)該使用固定的時(shí)間步長
while (self.lastStep < frameTime) {
  cpSpaceStep(self.space, SIMULATION_STEP);
  self.lastStep += SIMULATION_STEP;
}
- 避免死亡螺旋
 + cpSpaceStep()的計(jì)算造成幀率延遲的塔羅牌堆積效應(yīng)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末攻询,一起剝皮案震驚了整個(gè)濱河市从撼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌钧栖,老刑警劉巖低零,帶你破解...
    沈念sama閱讀 212,185評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異拯杠,居然都是意外死亡掏婶,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,445評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門潭陪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來雄妥,“玉大人,你說我怎么就攤上這事依溯±涎幔” “怎么了?”我有些...
    開封第一講書人閱讀 157,684評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵黎炉,是天一觀的道長枝秤。 經(jīng)常有香客問我,道長慷嗜,這世上最難降的妖魔是什么淀弹? 我笑而不...
    開封第一講書人閱讀 56,564評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮庆械,結(jié)果婚禮上薇溃,老公的妹妹穿的比我還像新娘。我一直安慰自己缭乘,他們只是感情好沐序,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,681評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般薄啥。 火紅的嫁衣襯著肌膚如雪辕羽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,874評(píng)論 1 290
  • 那天垄惧,我揣著相機(jī)與錄音刁愿,去河邊找鬼。 笑死到逊,一個(gè)胖子當(dāng)著我的面吹牛铣口,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播觉壶,決...
    沈念sama閱讀 39,025評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼脑题,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了铜靶?” 一聲冷哼從身側(cè)響起叔遂,我...
    開封第一講書人閱讀 37,761評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎争剿,沒想到半個(gè)月后已艰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,217評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蚕苇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,545評(píng)論 2 327
  • 正文 我和宋清朗相戀三年哩掺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涩笤。...
    茶點(diǎn)故事閱讀 38,694評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嚼吞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蹬碧,到底是詐尸還是另有隱情舱禽,我是刑警寧澤,帶...
    沈念sama閱讀 34,351評(píng)論 4 332
  • 正文 年R本政府宣布锰茉,位于F島的核電站呢蔫,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏飒筑。R本人自食惡果不足惜片吊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,988評(píng)論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望协屡。 院中可真熱鬧俏脊,春花似錦、人聲如沸肤晓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,778評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至漫萄,卻和暖如春卷员,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背腾务。 一陣腳步聲響...
    開封第一講書人閱讀 32,007評(píng)論 1 266
  • 我被黑心中介騙來泰國打工毕骡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人岩瘦。 一個(gè)月前我還...
    沈念sama閱讀 46,427評(píng)論 2 360
  • 正文 我出身青樓未巫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親启昧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子叙凡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,580評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容

  • 在iOS中隨處都可以看到絢麗的動(dòng)畫效果,實(shí)現(xiàn)這些動(dòng)畫的過程并不復(fù)雜密末,今天將帶大家一窺ios動(dòng)畫全貌握爷。在這里你可以看...
    每天刷兩次牙閱讀 8,471評(píng)論 6 30
  • 在iOS中隨處都可以看到絢麗的動(dòng)畫效果,實(shí)現(xiàn)這些動(dòng)畫的過程并不復(fù)雜苏遥,今天將帶大家一窺iOS動(dòng)畫全貌饼拍。在這里你可以看...
    F麥子閱讀 5,104評(píng)論 5 13
  • 書寫的很好赡模,翻譯的也棒田炭!感謝譯者,感謝感謝漓柑! iOS-Core-Animation-Advanced-Techni...
    錢噓噓閱讀 2,293評(píng)論 0 6
  • 顯式動(dòng)畫 顯式動(dòng)畫教硫,它能夠?qū)σ恍傩宰鲋付ǖ淖远x動(dòng)畫,或者創(chuàng)建非線性動(dòng)畫辆布,比如沿著任意一條曲線移動(dòng)瞬矩。 屬性動(dòng)畫 ...
    清風(fēng)沐沐閱讀 1,926評(píng)論 1 5
  • 前言 本文只要描述了iOS中的Core Animation(核心動(dòng)畫:隱式動(dòng)畫、顯示動(dòng)畫)锋玲、貝塞爾曲線景用、UIVie...
    GitHubPorter閱讀 3,607評(píng)論 7 11