CAMediaTiming 协议属性详解

来源:互联网 发布:matlab绘制数据分布图 编辑:程序博客网 时间:2024/05/17 01:17

我们都知道,CALayer和CAAnimation都实现了CAMediaTiming 协议,因此在Core Animation中,理解CAMediaTiming协议中的属性是非常必要的,但是苹果的文档中对于各个属性描述太简单,对初学者容易理解,这篇文章主要帮助理解CAMediaTiming协议中各个属性的含义。

CAMediaTiming Protocol提供了8个属性,下面将分别讲解。


duration

Specifies the basic duration of the animation, in seconds.
上面是官方文档的解释,这个属性一目了然,不需要做过多的解释,唯一有一点需要注意的是我们设置的duration可能和动画进行的真实duration不一样,这个依赖与superlayer的time space 或者就是speed。

speed

Specifies how time is mapped to receiver’s time space from the parent time space. (required)
其实也比较好理解,如果一个动画A :duration为1秒,speed为1;而另一个动画B:duration为2秒,speed为2。则两个动画的效果是相同的。不过前提是它们的super layer相同。

属性repeatCount , repeatDuration, autoreverses很容易理解,再此不在讲述。下面主要讨论剩下的三个属性

beginTime

Specifies the begin time of the receiver in relation to its parent object, if applicable.
如果一个animation是在一个animation group中,则beginTime就是其parent object——animation group 开始的一个偏移。如果一个animation 的 beginTime为5,则此动画在group aniamtion开始之后的5s在开始动画。
如果一个animation是直接添加在layer上,beginTime同样是是其parent object——layer 开始的一个偏移,但是一个layer的beginning是一个过去的时间(猜想layer的beginning可能是其被添加到layer tree上的时间),因此不能简单的设置beginTime为5去延迟动画5s之后开始,因为有可能layer的beginning加上5s之后也是一个过去的时间(很有可能),因此,当要延迟一个添加到layer上的动画的时候,需要定义一个addTime,因此
animation.beginTime = addTime + delay;

通过使用CACurrentMediaTime去获取addTime:
addTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];

如果一个layer他自己的beginTime已经设置,则animation的addTime的计算必须在layer的beginTime设置之后,因为要有一个时间的转移,具体看下面的例子:
CFTimeInterval currentTime = CACurrentMediaTime();CFTimeInterval currentTimeInSuperLayer = [superLayer convertTime:currentTime fromLayer:nil];layer.beginTime = currentTimeInSuperLayer + 2;CFTimeInterval currentTimeInLayer = [layer convertTime:currentTimeInSuperLayer fromLayer:superLayer];CFTimeInterval addTime = currentTimeInLayer;CAAnimationGroup *group = [CAAnimationGroup animation];group.beginTime = addTime + 1;group.animations = [NSArray arrayWithObject:anim];group.duration = 2;anim.beginTime = 0.5;[layer addAnimation:group forKey:nil];

timeOffset

Specifies an additional time offset in active local time. (required)
此句话不太容易理解,但是通过一个例子很容易理解。
假定一个3s的动画,它的状态为t0,t1,t2,t3,当没有timeOffset的时候,正常的状态序列应该为:
t0->t1->t2->t3
当设置timeOffset为1的时候状态序列就变为
t1->t2->t3->t0
同理当timeOffset为2的时候状态序列就变为:
t2->t3->t0=>t2
是不是理解了?

下面举一个例子,效果图参见空间图片地址http://my.csdn.net/my/album/detail/1651105 (不知道怎么直接嵌入的,因为是个gif,直接上传也不会播放,哪位同学知道好的处理方法可以告诉我)

主要代码如下:
// Add layer.CATextLayer *A = [CATextLayer layer];A.string = @"A";A.fontSize = 48;A.foregroundColor = [UIColor blackColor].CGColor;A.bounds = CGRectMake(0, 0, 48, 48);A.position = self.center;[self.layer addSublayer:A];// Move animation.CAKeyframeAnimation *move = [CAKeyframeAnimation animationWithKeyPath:@"position"];move.values = [NSArray arrayWithObjects:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMinX(self.bounds), CGRectGetMaxY(self.bounds))], [NSValue valueWithCGPoint:CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMinY(self.bounds))], [NSValue valueWithCGPoint:CGPointMake(CGRectGetMaxX(self.bounds), CGRectGetMaxY(self.bounds))], nil];move.calculationMode = kCAAnimationCubic;move.duration = 10;move.speed = 2;// Opacity animation.CABasicAnimation *opacity = [CABasicAnimation animationWithKeyPath:@"opacity"];opacity.toValue = [NSNumber numberWithFloat:0];opacity.duration = 2.5;opacity.beginTime = 2.5; // Fade from the half way.// Animatin group.CAAnimationGroup *group = [CAAnimationGroup animation];group.animations = [NSArray arrayWithObjects:move, opacity, nil];group.duration = 8;group.repeatCount = HUGE_VALF;// Time warp.CFTimeInterval currentTime = CACurrentMediaTime();CFTimeInterval currentTimeInSuperLayer = [self.layer convertTime:currentTime fromLayer:nil];A.beginTime = currentTimeInSuperLayer + 5; // Delay the appearance of A.CFTimeInterval currentTimeInLayer = [A convertTime:currentTimeInSuperLayer fromLayer:self.layer];CFTimeInterval addTime = currentTimeInLayer;group.beginTime = addTime + 3; // Delay the animatin group.[A addAnimation:group forKey:nil];// Timer. For nice visual effect. Optional.CATextLayer *timer = [CATextLayer layer];timer.fontSize = 48;timer.foregroundColor = [UIColor redColor].CGColor;timer.bounds = CGRectMake(0, 0, 48, 48);timer.position = self.center;[self.layer addSublayer:timer];CAKeyframeAnimation *count = [CAKeyframeAnimation animationWithKeyPath:@"string"];count.values = [NSArray arrayWithObjects:@"5", @"4", @"3", @"2", @"1", nil];CABasicAnimation *fade = [CABasicAnimation animationWithKeyPath:@"transform.scale"];fade.toValue = [NSNumber numberWithFloat:0.2];group = [CAAnimationGroup animation];group.animations = [NSArray arrayWithObjects:count, fade, nil];group.duration = 5;[timer addAnimation:group forKey:nil];

大概解释一下,其实就是先播放一个倒计时5-4-3-2-1的动画,之后在显示layer A,因为A的beginTime为5,而当A显示3秒之后,A上才开始做group的动画。

fillMode

文档中关于fillMode的讲解也不是很清楚,fillMode有4中类型
kCAFillModeRemoved (default)
kCAFillModeForwards
kCAFillModeBackwards
kCAFillModeBoth

用语言去解释这些属性,会让人难以理解,所以这里用例子去解释,看下面代码:
CALayer *colorLayer = [[ CALayer alloc] init];colorLayer.position = self.center;colorLayer.backgroundColor = [UIColor redColor].CGColor;colorLayer.bounds = CGRectMake(0.0f, 0.0f, 20.0f, 20.0f);[self.layer addSublayer:colorLayer];        CABasicAnimation *boundAn = [CABasicAnimation animationWithKeyPath:@"bounds"];boundAn.fromValue = [NSValue valueWithCGRect:CGRectMake(0.0f, 0.0f, 100.0f, 100.0f)];boundAn.toValue = [NSValue valueWithCGRect:CGRectMake(0.0f, 0.0f, 400.0f, 400.0f)];boundAn.beginTime = 2.0f;boundAn.duration = 5.0f;boundAn.fillMode = kCAFillModeRemoved;CAAnimationGroup *group = [CAAnimationGroup animation];group.animations = [NSArray arrayWithObject:boundAn];group.duration = 10.0f;        [colorLayer addAnimation:group forKey:nil];

kCAFillModeRemoved也是fillMode的默认属性,此时动画的效果:开始时,colorLayer的size为(20,20),当到2s的时候,colorLayer的size突然就变为(100,100),然后开始做动画,当到7s的时候colorLayer的duration已经完成,此时colorLayer的size会突然 变为(20,20),然后在持续3s,当总时间到10s时结束。

当fillMode的属性设置为kCAFillModeForwards的时候,动画效果为:开始时,colorLayer的size为(20,20),当到2s的时候,colorLayer的size突然就变为(100,100),然后开始做动画,之前都和kCAFillModeRemoved都一样,不一样的时当到7s的时候colorLayer的duration已经完成,此时colorLayer的size还会保持在(400,400),然后在持续3s,当总时间到10s时结束,此时size才变为(20,20)

当fillMode的属性设置为kCAFillModeBackwards的时候,动画效果为:开始时,colorLayer的size就为(100,100),当到2s的时候,colorLayer开始做动画,当到7s的时候colorLayer的duration已经完成,此时colorLayer的size会突然 变为(20,20),然后在持续3s,当总时间到10s时结束。

kCAFillModeBoth就不在解释了,猜都能猜到应该是kCAFillModeForwards和kCAFillModeBackwards的结合。


至此,应该对CAMediaTiming 协议中的属性应该有一定了解了。
本文参考了苹果官方文档 CAMediaTiming Protocol Preference 以及博文 time warp in animation

原创粉丝点击