CAMediaTiming 协议属性详解

我们都知道,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

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值