CAMediaTiming协议
动画所有跟时间相关的属性(duration, beginTime, repeatCount等)都来自于CAMediaTiming协议,它由CALayer和CAAnimation及其子类实现。协议一共定义了8个属性,通过这8个属性就能完全地控制动画时间。
beginTime
beginTime可以做到延迟执行动画的效果,比如延迟一秒:beginTime=CACurrentMediaTime()+1;
repeatCount和repeatDuration
repeatCount和repeatDuration都可以控制重复执行动画,当二者不可同时使用。repeatCount指定重复的次数(可以是小数,如1.5),repeatDuration指定重复执行持续的时间(到期就停止)。
fillMode
如果要让动画在开始之前(延迟的这段时间内)显示fromValue的状态,你可以设置动画向后填充:设置fillMode为kCAFillModeBackwards。同理如果让动画结束后停留在toValue的状态,就应该设置为kCAFillModeForwards。如果两种都要有,就设置kCAFillModeBoth。
注意必须配合animation.removeOnCompletion = NO
才能达到以上效果。建议直接修改ModelLayer的属性值来实现,这样就不用考虑动画的生命周期了。
autoreverses
将使动画先正常走,完了以后反着从结束值回到起始值(所有动画属性都会反过来,比如动画速度,如果正常的是先快后慢,则反过来后变成先慢后快)。如果duration为1s,则完成一次autoreverse就需要2s。
speed
如果把动画的duration设置为3秒,而speed设置为2,动画将会在1.5秒结束,因为它以两倍速在执行。
动画速度是有层级关系的:一个动画的speed为1.5,它同时是一个speed为2的动画组的一个动画成员,则它将以3倍速度被执行;如果再将这个动画组添加到一个speed为2的Layer上,则最终将以6倍速度执行。(CAAnimation,CAAnimationGroup,CALayer都实现了CAMediaTiming协议)
timeOffset
这个属性实际上并不会自己单独使用,而会结合一个暂停动画(speed=0)一起使用来控制动画的“当前时间”。暂停的动画将会在第一帧卡住,然后通过改变timeOffset来随意控制动画进程。
举个例子:比如一个改变位置的动画,让一个视图从(0,0)移动到(100,100),持续时间为1秒。如果先暂停动画,然后设置timeOffset为0.5,那么首先动画会卡在“第一帧”,而第一帧由timeOffset决定,也就是动画正常运作时间进行到0.5秒的那一帧就是“第一帧”,这时候动画就会停在(50,50)的地方。注意timeOffset是具体的秒数而不是百分比。
动画的暂停和恢复
-(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;
}