Core Animation 文檔翻譯 (第六篇)—高級動畫技巧

 

前言


配置屬性動畫或者關鍵幀動畫的方式是多種多樣的。須要同時執行多個動畫或者順序執行多個動畫的APP,能夠經過高級的方式同步這些動畫的timing或者將這些動畫綁定在一塊兒。咱們也可使用其餘類型的動畫對象來建立可視化的transitions和別的有趣的動畫效果。緩存

 

過渡動畫支持Layer可見性的變化


就像本級標題名字所說同樣,一個transition動畫對象爲Layer建立一個動畫性的過渡效果。transistion對象最經常使用的方法就是以協調的方式讓一個Layer動畫形式的出現,並讓另一個Layer動畫形式的消失。和屬性動畫不同,屬性動畫是改變Layer的一個屬性;而transition動畫操做layer緩存的image用來建立可視化效應,經過只調整屬性這些可視化效應是很難或者幾乎不願能完成的。標準的transition類型能夠用來實現漸顯、push、移除或者交叉漸隱動畫。在OSX上,咱們也可使用Core image filter建立具備特殊效應的transitions,例如擦拭、卷頁、波紋或者自定義的其餘效果。app

爲了執行transition動畫,咱們能夠建立CATransition對象並將其添加到相關的Layers。咱們在使用transition對象的時候能夠指定transition的類型、開始和結束進度點。開始動畫前,能夠設置開始和結束進度值,這兩個值可讓咱們的transition動畫看起來像從開始值開始,和結束值結束。函數

代碼5-1展現瞭如何在兩個View之間建立push 過渡動畫。在這個例子中,myView1和myView2是在同一個父視圖上相同的position,而且myView1是可見的在最初。動畫效果爲myView1想作滑出知道徹底隱藏,同時myView2從右邊滑入知道徹底顯示。爲了確保在動畫的結束時候兩個view相應的可見性是正確的,咱們須要更新兩個view的hidden屬性。性能

 

代碼5-1在iOS中兩個view之間過分動畫
CATransition* transition = [CATransition animation];
transition.startProgress = 0;
transition.endProgress = 1.0;
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromRight;
transition.duration = 1.0;
 
// Add the transition animation to both layers
[myView1.layer addAnimation:transition forKey:@"transition"];
[myView2.layer addAnimation:transition forKey:@"transition"];
 
// Finally, change the visibility of the layers.
myView1.hidden = YES;
myView2.hidden = NO;

 

當兩個layer都須要相同的過分動畫時候,咱們可讓他們使用相同的transition對象。使用相同的transition對象也能簡化代碼。動畫

 

自定義動畫時間函數


時間控制函數是動畫的重要部分。經過核心動畫中CAMediaTiming協議的方法和屬性,咱們能夠爲動畫指定精確的時間信息。CAAnimation類遵照該協議,所以咱們可以指定動畫對象的時間信息,隱式動畫對象默認封裝了這些信息,並優先使用默認的信息。spa

對於如何理解時間信息和動畫時,理解Layer對象和time之間關係是很重要的。每一個Layer有他們本身的局部時間,Layer使用本身的局部時間來管理動畫時間。一般狀況下,兩個不一樣Layer的局部時間是很是接近的,以致於在爲這兩個Layer指定相同的時間值時,用戶也察覺不到。然而,Layer的局部時間可以被它的父Layer和它自身的時間參數所修改。例如,改變Layer的[speed]屬性可以引發Layer(和他的sublayer)的動畫的duration發生成比例的變化。code

爲了幫助咱們確保時間值是恰當的,CALayer類定義了convertTime:fromLayer: and convertTime:toLayer:方法。咱們可使用這些方法將一個修正的時間值轉換爲layer的局部時間,或者將一個layer的時間值轉換到另一個Layer。這兩個方法涉及到時間相關的屬性並返回一個值,咱們將這個值能夠用於別的layer,這兩個方法所涉及到的時間屬性也會影響layer的局部時間。代碼5-3展現了按期用於得到一個layer的當前局部時間。經過CACurrentMediaTime函數能夠獲取計算機當前時間,同時可將這個時間用於轉換出Layer的局部時間。orm

 

代碼5-3過的Layer的本地時間
CFTimeInterval localLayerTime = [myLayer convertTime:CACurrentMediaTime() fromLayer:nil];

 

一旦咱們有了相對於layer局部時間的值,咱們可使用該值去更新動畫對象或Layer的時間相關的屬性。經過設置這些時間屬性,咱們能夠得到許多有趣的動畫行爲,這些屬性包含如下幾種:對象

  • 使用beginTime屬性設置動畫的開始時間。一般,動畫在下個更新循環開始執行。咱們可使用beginTime參數去延遲幾秒動畫的開始。將兩個動畫順序的關聯在一塊兒的方法就是,將一個動畫的beginTime和另一個動畫的結束值設置爲相同的值。
    若是咱們延遲動畫的開始時間,咱們也應該設置fillModel屬性的值爲kCAFillModeBackwards。這個模式將會使Layer顯式動畫的開始值,及時圖層樹上的Layer對象具備不一樣的值。若是不設置這個模式,咱們將會看到一個到最終值跳躍性的顯式在動畫開始執行前。其餘的模式也是可用的。
  • autoreverses屬性將會引起動畫以被指定的duration返回動畫的開始值。咱們將這個屬性與repeatCount屬性結合起來能夠實如今開始值和結束值之間來回作動畫。若是autoreversing爲YES併爲repeatCount屬性設置整數值(例如1.0),那麼將會引發動畫中止在開始值;添加額外的一半動畫(例如設置爲1.5)將會使得動畫中止在結束值的位置。ci

  • 在組動畫中使用timeOffset屬性可以讓一些動畫在組內某些動畫以後開始。

 

暫停和重啓動畫


爲了暫停動畫,咱們能夠利用Layer遵照的CAMediaTiming協議,並設置Layer動畫的speed爲0.0。將speed設置爲0將引發動畫暫停,直到咱們改變這個值爲非0值動畫纔會結束暫停。代碼5-4展現了簡單的示例關於如何暫停和在暫停後重啓動畫。

 

5-4暫停和重啓Layer的動畫
-(void)pauseLayer:(CALayer*)layer {
   CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
   layer.speed = 0.0;
   layer.timeOffset = pausedTime;
}
 
-(void)resumeLayer:(CALayer*)layer {
   CFTimeInterval pausedTime = [layer timeOffset];
   layer.speed = 1.0;
   layer.timeOffset = 0.0;
   layer.beginTime = 0.0;
   CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
   layer.beginTime = timeSincePause;
}

 

顯式動畫幫助咱們改變更畫的參數


爲Layer作的每個改變必須是transaction的一部分。[CATransaction]類管理動畫的建立、將動畫組合在一塊兒並將組合的動畫以恰當的時間執行。大部分狀況下,咱們不須要建立本身的transactions。不管什麼時候你爲Layer添加顯式和隱式動畫,核心動畫自動建立隱式transaction。然而,咱們也能建立顯式transactions去更準確的管理這些動畫。

使用CATransaction類的方法,咱們能夠建立和管理transactions。調用begin類方法開始(隱式的建立)新的transaction;調用commit類方法結束transaction。在這兩個方法之間調用咱們想要做爲transaction其中的變化。例如咱們使用代碼5-5變化layer的兩個屬性。

 

5-5建立顯式的transaction
[CATransaction begin];
theLayer.zPosition=200.0;
theLayer.opacity=0.0;
[CATransaction commit];

 

使用transactions最主要的緣由就是在transaction的beginTime和commit中間,咱們能夠改變duration,timing函數和其餘參數。咱們可以也可以爲transaction關聯一個完成後執行的block,方便咱們的APP可以在這組動畫結束後的到通知。改變更畫的參數,須要經過修改在使用setValue:forKey:方法修改transaction字典裏面對應的key。例如,改變默認duration爲10秒,咱們應該改變kCATransactionAnimationDuration key,例如代碼5-6展現

 

5-6改變更畫的默認duration
[CATransaction begin];
[CATransaction setValue:[NSNumber numberWithFloat:10.0f]
                 forKey:kCATransactionAnimationDuration];
// Perform the animations
[CATransaction commit];

 

當咱們想要爲不一樣的動畫集合提供不一樣的值時,咱們能夠嵌套transactions。若是想要嵌套,只須要在begin類方法以後再次調用begin方法。每個begin調用必須和-個commit方法對應。僅當咱們提交最後一個最外層的commit方法時,核心動畫纔會開始相關的動畫。

代碼5-7展現了兩個transaction的嵌套。在這個例子中這個內層的和外層的transaction改變相同的動畫參數,可是使用不一樣的值。

 

5-7嵌套顯式的transaction
[CATransaction begin]; // Outer transaction
 
// Change the animation duration to two seconds
[CATransaction setValue:[NSNumber numberWithFloat:2.0f]
                forKey:kCATransactionAnimationDuration];
// Move the layer to a new position
theLayer.position = CGPointMake(0.0,0.0);
 
[CATransaction begin]; // Inner transaction
// Change the animation duration to five seconds
[CATransaction setValue:[NSNumber numberWithFloat:5.0f]
                 forKey:kCATransactionAnimationDuration];
 
// Change the zPosition and opacity
theLayer.zPosition=200.0;
theLayer.opacity=0.0;
 
[CATransaction commit]; // Inner transaction
 
[CATransaction commit]; // Outer transaction

 

爲動畫添加觀看者視角


APP能夠在三個維度控制Layer;簡單的核心動畫所展現的Layers是使用了平面投射,本質就是核心動畫將3維空間投射到2維平面上了。默認狀況下,具備相同尺寸和不一樣zPosition的Layers看起來像是同樣大的,即便他們在Z軸上的座標是不一樣的,也就是說咱們不能想正常的人眼視角觀看這些三維場景。然而,咱們能夠經過修改Layers的transformation矩陣,加入人眼觀看視角。
當調整一個三維場景的視角時,咱們須要調整superlayer的sublayerTransform矩陣(superlayer包含這些可被看到的layers),經過調整superlayer可以簡化代碼的工做量(若是不經過調整superlayer那麼咱們就須要把相同的視角相關信息應用到全部的子Layer),同時他也確保了視角是正確應用到同級的sublayers上(同級的sublayers可能在不一樣的平面重疊交叉)。

代碼5-8展現了爲父Layer建立簡單的視角transform。在這種狀況下,自定義的人眼視角的變化將會改變沿着Z軸到Layer的距離。一般爲了保證Layers以指望的方式,咱們爲人眼視角指定一個正數值。數值越大看到的越遠,數值越小看到的會越細緻。

 

代碼5-8爲父Layer添加視角transform
CATransform3D perspective = CATransform3DIdentity;
perspective.m34 = -1.0/eyePosition;
 
// Apply the transform to a parent layer.

 

在相似之上配置了父Layer狀況下,咱們能夠改變任何子Layer的zPosition屬性,並觀察它們的尺寸(在基於它們到人眼位置)是如何變化的。

相關文章
相關標籤/搜索