有許多方式能夠配置你的 property-based 或 keyframe 動畫,這些方式能夠爲你作不少。若想讓 App 同時或者按順序表現多個動畫,你可使用更多高級的行爲來同步這些動畫的時間或者動畫的鏈條。你也可使用其餘動畫類型對象建立視覺過分和其餘有意思的動畫效果。緩存
就像名字同樣,一個過分動畫對象爲一個 layer 建立一個動畫的視覺過分。最日常的過分對象使用是在一個座標行爲中一個 layer 的顯現和另外一個 layer 的消失。不像 property-based 動畫,在動畫改變 layer 的屬性的地方,一個過分動畫操縱一個 layer 的緩存圖像以建立視覺效果,單靠改變屬性是很困難或者不可能的。標準的過分類型使你表現重現、推、移動或者淡入淡出動畫。在 OS X 中,你也可使用 Core Image 濾鏡建立過分,使用其餘影響類型,好比掃、翻頁、波紋、或者你設計的自定義效果。app
爲了建立一個過分動畫,你要建立一個 CATransition 對象,並且要把它添加到過分中包括的 layer。你使用過分對象明確過分類型,表現、開始和結束過分動畫的點。你不須要使用整個的過分動畫。當動畫時,過分對象使你明確起始進度值的使用。這些值使你在動畫的中點作一些事情,好比開始或結束這個動畫。動畫
代碼 5-1 展現了在兩個視圖之間建立一個 push 過渡動畫的代碼。在這個例子中,myView1 和 myView2 位於同一個父層視圖中,位置都是相同的,只是 myView1 是當前可見的視圖。push 過渡動畫致使 myView1 向左淡出直至消失,同時 myView2 從右邊淡入成爲當前可見視圖。在動畫結束的時候更新兩個 hidden 屬性,以便這兩個視圖正確顯現。設計
代碼 5-1 Animating a transition between two views in iOScode
CATransition *transition = [CATransition animation]; transition.startProgress = 0; transition.endProgress = 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 被包括進同一個過渡中,你能夠爲他們使用同一個過渡對象。使用同一個過渡對象簡化了代碼。然而,當每一個 layer 的過渡的參數不一樣時,就須要使用多個過渡對象了。orm
代碼 5-2 展現了在 OS X 上怎麼使用 Core Image 濾鏡實現過渡效果。用你想要的參數配置完濾鏡後,把它賦給過渡對象的 filter 屬性。以後的動畫應用過程和其餘動畫對象的類型相同。對象
代碼 5-2 Using a Core Image filter to animate a transition on OS X事務
// Create the Core Image filter, setting several key parameters. CIFilter *aFilter = [CIFilter filterWithName:@"CIBarsSwipeTransition"]; [aFilter setValue:[NSNumber numberWithFloat:3.14] forKey:@"inputAngle"]; [aFilter setValue:[NSNumber numberWithFloat:30.0] forKey:@"inputWidth"]; [aFilter setValue:[NSNumber numberWithFloat:10.0] forKey:@"inputBarOffset"]; // Create the transition object CATransition *transition = [CATranstion animation]; transition.startProgress = 0; transition.endProgress = 1.0; transition.filter = aFilter; transition.duration = 1.0; [self.imageView2 setHidden:NO]; [self.imageView.layer addAnimation:transition forKey:@"transition"]; [self.imageView2.layer addAnimation:transition forKey:@"transition"]; [self.imageView setHidden:YES];
注意:當在動畫中使用 Core Image 濾鏡時,最困難的部分是配置濾鏡。例如,使用 bar swipe 過渡,肯定一個 input angle 過高或者過低均可能會形成它看起來沒有發生過渡。若是你沒有看到指望的動畫,嘗試着調整濾鏡的參數,查看參數值的變化十分產生變化的結果。ip
時間是動畫中很重要的部分,經過 Core Animation 協議 CAMediaTiming 的方法和屬性指明動畫的時間精度信息。有兩個 Core Animation 類使用這個協議。CAAnimation使用它,你能夠經過這個類的實例指定時間信息。CALayer 也使用這個協議,儘管隱性的動畫一般具備優先默認的時間信息,你也可使用一些相關的時間屬性配置它。ci
當考慮動畫和時間時,理解 layer 對象怎麼用時間工做很重要。每個 layer 都有它本身用來管理動畫計時的本地時間。通常兩個不一樣的 layer 的本地時間是很接近的,你能夠爲他們使用同一個時間值而用戶可能不會注意到。可是本地時間能夠被它的父層 layer 或者自身的計時參數修改。好比,改變 layer 的 speed 屬性會致使自身(子層 layer)動畫的持續時間相應地變化。
爲了協助你爲給定的 CALayer 肯定合適的時間值,CALayer 類定義了 convertTime:fromeLayer: 和 convertTime:toLayer: 方法。你能夠用這些方法轉換一個固定的時間值爲 layer 的本地時間或者把一個 layer 的時間值轉換爲另外一個的。這兩個方法考慮了可能影響 layer 本地時間的媒體時間屬性,並且返回一個你能夠在其餘 layer 使用的值。代碼 5-3 展現了常規下得到一個 layer 的當前本地時間。CACurrentMediaTime 方法是一個很方便的方法,返回當前電腦的時鐘時間,會被轉換爲 layer 的本地時間。
代碼 5-3 Getting a layer's current local time
CFTimeInterval localLayerTime = [myLayer convertTime:CACurrentMediaTime() fromLayer:nil];
一旦你有了 layer 的本地時間值,你可使用它更新動畫對象或者 layer 時間相關的屬性。使用這些時間屬性,你能夠得到一些有趣的動畫行爲,包括:
你能夠利用 layer 實現 CAMediaTiming 協議,而後設置 layer 的動畫速度爲 0.0,會使動畫暫停。設置速度爲 0 會暫停動畫直至你變爲非零值。代碼 5-4 展現了一個如何暫停和恢復動畫的簡單例子。
代碼 5-4 Pausing and resuming a layer's animations
-(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; }
你作的每個改變必須是事務的一部分。CATransaction 類管理動畫的建立和聚合,還有動畫在合適時間的執行。多數狀況下,你不須要建立本身的事務。不管你在何時爲 layer 添加隱性或顯性動畫, Core Animation 自動地建立了一個隱性事務。可是你也能夠建立本身的事務,更大粒度的管理這些動畫。
你用 CATransaction 類的方法建立和管理事務。調用類方法 begin 開始(隱性建立)一個新的事務;調用類方法 commit 結束事務。在這兩個方法調用中間是你想作的事務部分的改變。例如,改變 layer 的兩個屬性,你可使用代碼 5-5 中的代碼。
代碼 5-5 Creating an explicit transaction
[CATransaction begin]; theLayer.zPosition = 200.0; theLayer.opacity = 0.0; [CATransaction commit];
使用事務的最主要緣由之一是由於在一個顯式的事務限制以內,你能夠改變持續時間,時間方法和其餘的參數。你也能夠賦給整個事務一個完整的 block,以便你的 app 在一組動畫完成時收到通知。改變更畫參數須要使用 setValue:forKey: 方法修改事務字典的合適鍵。例如,更改默認持續時間到 10 秒,你將改變 kCATransactionAnimationDuration 鍵,如代碼 5-6
代碼 5-6 Changing the default duration of animaitons
[CATransaction begin]; [CATransaction setValue:[NSNumber numberWithFloat:10.0f] forKey:kCATransactionAnimationDuration]; // Perform the animations [CATransaction commit];
你能夠在想爲不一樣的動畫集提供不一樣的默認值時疊加事務。把一個事務疊加到另外一箇中,只須要再一次調用類方法 begin。每一次 begin 的調用必須有一個相對應的 commit 方法調用。只有你爲最外面的事務提交了變動 Core Animation 纔開始相關的動畫。
代碼 5-7 展現了一個嵌套的事務。在這個例子中,內層的事務像外層同樣改變了同一個動畫的參數,可是使用了不一樣的值。
代碼 5-7 Nesting explicit transactions
[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,可是爲了簡單 Core Animation 使用一個平行項目顯示 layer,這個項目把場景平植到一個二維平面中。這個默認的行爲致使相同尺寸不一樣 zPosition 值的 layer 以同一個尺寸展示,即便他們在 z 軸上相差很遠。通常狀況下你看到的三維場景透視就不存在啦。可是,你能夠修改 layer 的 transformation matrix 包含透視信息來改變這個行爲。
當修改場景的透視時,你須要修改包含了被看到的視圖的父層 layer 的 sublayerTransform 矩陣。修改父層 layer 簡化了你不得不寫的應用到全部子層的透視信息的代碼。它還確保了透視能被正確的應用到在不一樣平面上重疊的兄弟層 layr。
代碼 5-8 展現了建立一個父層 layer 的簡單透視 transform 代碼。在這裏自定義的 eyePosition 變量指明瞭沿着 z 軸到視圖的相對距離。通常你爲 eyePosition 指定一個正數,以便保持 layer 的水平。在一個平面視圖中會有更大的值,而更小的值會致使不一樣的 layer 之間產生戲劇性的視覺效果。
代碼 5-8 Adding a perspective transform to a parent layer
CATransform3D perspective = CATransform3DIdentity; perspective.m34 = -1.0/eyePosition; // Apply the transform to a parent layer. myParentLayer.sublayerTransform = perspective;
使用父層 layer 的配置,你能夠改變任意子層 layer 的 zPosition 屬性,並且還能夠觀察它們的尺寸是如何基於它們的相對距離從視覺位置改變的。