iOS CAAnimation(四)控制動畫過程

Timing is an important part of animations, and with Core Animation you specify precise timing information for your animations through the methods and properties of the CAMediaTiming protocol. Two Core Animation classes adopt this protocol. The CAAnimation class adopts it so that you can specify timing information in your animation objects. The CALayer also adopts it so that you can configure some timing-related features for your implicit animations, although the implicit transaction object that wraps those animations usually provides default timing information that takes precedence.

When thinking about timing and animations, it is important to understand how layer objects work with time. Each layer has its own local time that it uses to manage animation timing. Normally, the local time of two different layers is close enough that you could specify the same time values for each and the user might not notice anything. However, the local time of a layer can be modified by its parent layers or by its own timing parameters. For example, changing the layer’s speed property causes the duration of animations on that layer (and its sublayers) to change proportionally.

時間是動畫中很重要的一個概念,我們可以通過CAMediaTiming協議提供的屬性來控制動畫的時間相關內容。

@interface CAAnimation : NSObject <NSSecureCoding, NSCopying, CAMediaTiming, CAAction>
@interface CALayer : NSObject <NSSecureCoding, CAMediaTiming>

CAAnimation遵守了該協議,我們可以使用該協議指定創建動畫中的時間信息。

CALayer也遵守了該協議,隱式動畫自動包裝了默認時間信息以供使用,我們可以通過這個方式控制隱式動畫的時間相關特性。

每個layer都有着自己的local time(管理動畫時間),不同layer之間的local time是獨立的。但是如果layer之間存在父子layer關係的話,子layer就受到到父layer的影響,比如修改父layer的speed屬性,子layer同樣會受到影響。

爲了確保時間值適合相應的圖層,CALayer該類定義convertTime:fromLayer:convertTime:toLayer:方法。可以使用這些方法將固定時間值轉換爲圖層的本地時間(local time),或將時間值從一層轉換爲另一層。這些方法考慮了可能影響該圖層本地時間的媒體計時屬性,並返回了可與其他圖層一起使用的值。

//獲取layer層的local time
CFTimeInterval localLayerTime = [myLayer convertTime:CACurrentMediaTime()fromLayer:nil];
@protocol CAMediaTiming

/*Use the beginTime property to set the start time of an animation. Normally,
 animations begin during the next update cycle. You can use the beginTime parameter
 to delay the animation start time by several seconds. The way to chain two 
animations together is to set the begin time of one animation to match the end time
 of the other animation.*/
//通過這個屬性可以控制動畫的開始時間, 可以用來延遲A動畫的開始是其在B動畫完成時再開始 
//默認值0 在下一輪runloop循環開始做動畫
@property CFTimeInterval beginTime;

//持續時間 默認值0
@property CFTimeInterval duration;

//動畫速度 默認值1
@property float speed;

/* Additional offset in active local time. i.e. to convert from parent
 * time tp to active local time t: t = (tp - begin) * speed + offset.
 * One use of this is to "pause" a layer by setting `speed' to zero and
 * `offset' to a suitable value. Defaults to 0. */
//這個值一般用來實現 暫停和恢復 動畫。
//公式:t = (tp - begin) * speed + offset.
@property CFTimeInterval timeOffset;

/* The repeat count of the object. May be fractional. Defaults to 0. */
@property float repeatCount;

/* The repeat duration of the object. Defaults to 0. */
@property CFTimeInterval repeatDuration;

/*The autoreverses property causes an animation to execute for the specified duration
 and then return to the starting value of the animation. You can combine this
 property with the repeatCount property to animate back and forth between the start
 and end values. Setting the repeat count to a whole number (such as 1.0) for an 
autoreversing animation causes the animation to stop on its starting value. Adding 
an extra half step (such as a repeat count of 1.5) causes the animation to stop on 
its end value.*/
//在指定的動畫完成後是否倒着回到動畫開始時的值,可以配合repeatCount屬性以實現在開始、結束值之間
//來回動畫的重複播放。如果是整數值,則會有一個開始值->結束值->開始值來回循環,如果是帶0.5的小數
//值,比如1.5,動畫就會停止在結束的值。 默認值0
@property BOOL autoreverses; 

/* Defines how the timed object behaves outside its active duration.
 * Local time may be clamped to either end of the active duration, or
 * the element may be removed from the presentation. The legal values
 * are `backwards', `forwards', `both' and `removed'. Defaults to
 * `removed'. */
@property(copy) CAMediaTimingFillMode fillMode;

@end

fillMode解釋:

舉一個具體的例子:

暫停和恢復動畫:

// t(本層的時間) = (tp(父層的時間) - begin) * speed + timeOffset
//通過控制layer的speed屬性來控制動畫的啓動暫停
-(void)pauseLayer:(CALayer *)layer {
   CFTimeInterval pausedTime = [layerLayerTime: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 = [layerLayerTime:CACurrentMediaTime()fromLayer:nil]-pausedTime;
   layer.beginTime = timeSincePause;
}

Transactions(動畫事務):

Every change you make to a layer must be part of a transaction. The CATransaction class manages the creation and grouping of animations and their execution at the appropriate time. In most cases, you do not need to create your own transactions. Core Animation automatically creates an implicit transaction whenever you add explicit or implicit animations to one of your layers. However, you can also create explicit transactions to manage those animations more precisely.

當我們給layer添加顯式或隱式動畫時,CoreAnimation會自動創建一個隱式的transaction動畫事務,CATransaction會管理動畫的創建和執行。

我們也可以創建顯式的動畫事務更精準地管理動畫。

在begin和commit方法中間通過setValue:forKey:的方式賦值。

CA_EXTERN NSString * const kCATransactionAnimationDuration
CA_EXTERN NSString * const kCATransactionDisableActions
CA_EXTERN NSString * const kCATransactionAnimationTimingFunction
CA_EXTERN NSString * const kCATransactionCompletionBlock
//修改動畫的默認持續時間
[CATransaction begin];
[CATransaction setValue:[NSNumber numberWithFloat:10.0f]
                 forKey:kCATransactionAnimationDuration];
//執行動畫
[CATransaction commit];
//嵌套使用
[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

我們可以通過動畫事務來隱藏layer的動畫:

You can temporarily disable layer actions using the CATransaction class. When you change the property of a layer, Core Animation usually creates an implicit transaction object to animate the change. If you do not want to animate the change, you can disable implicit animations by creating an explicit transaction and setting its kCATransactionDisableActions property to true. Listing 6-2 shows a snippet of code that disables animations when removing the specified layer from the layer tree.

[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue
                 forKey:kCATransactionDisableActions];
[aLayer removeFromSuperlayer];
[CATransaction commit];

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章