理解CAMediaTiming的beginTime

CALayer和CAAnimation都实现了CAMediaTiming协议。CAMediaTiming协议中有一个beginTime属性。这里记录一些对beginTime属性的理解。

1、全局时间。Core Animation使用一个所谓的全局时间坐标系。这个全局时间坐标系的原点为设备重启完成的那个时刻,当前时间为“现在”距离“起始点”的秒数。CACurrentMediaTime函数即可返回这个秒数。

2、层级和局部时间。layer和animation之间存在父子关系,从而形成层级。另一方面,每个layer或animation都有一个属于自己的局部时间坐标系。beginTime即表示自己的时间坐标系的原点相对于父的时间坐标系的原点的偏移值。这里的父与子的时间坐标系的关系(通过beginTime表示偏移)类似与父与子的空间坐标系的关系(通过frame.origin表示偏移)。

例如,当存在这个层级关系时:layer1 -> layer2 -> animation1 -> animaiton2。

- layer1为根layer,layer1.beginTime表示layer1的局部时间坐标系的原点与全局时间坐标系的原点的偏移。

- layer2为layer1的子layer,layer2.beginTime表示layer2的局部时间坐标系的原点与layer1的局部时间坐标系的原点的偏移。

- animation1为layer2的animation,animation1.beginTime表示animation1的局部时间坐标系的原点与layer2的局部时间坐标系的原点的偏移。

- animation2为animation1的子animation,animation2.beginTime表示animation2的局部时间坐标系的原点与animation1的局部时间坐标系的原点的偏移。

3、几个重要的点。

- 根layer。上面已经提到过,对于根layer,其beginTime表示其局部时间坐标系的原点与全局时间坐标系的原点的偏移。

- “根animation”(这里指的是直接添加到layer的动画,即上面例子里的animation1的情况;而animation2不属于这个情况)。当其beginTime为0时,Core Animation会有一个特别的操作:当layer被commited时,如果layer的直接animation的beginTime为0,那么会将这个animation的beginTime设置为CACurrentMediaTime(),即设置为当前时间。再次强调,仅对“根animation”有这个操作,其他animation不会有这个操作。

== 另一方面,为什么要有这个操作呢?应该就是为了方面开发人员。因为,通常来说,我们为layer加入动画,是需要马上开始执行这个动画的。

== 当我们不想要这个特别的操作,但又想“根animation”的局部时间坐标系的原点与父layer的局部时间坐标系的原点的偏移为0时,只需要将“根animation”的beginTime设置为一个“不为0而且很小很小的数”即可。AVCoreAnimationBeginTimeAtZero就是用来这个用途的。

- 其他layer和其他animation。没有什么特别操作,其beginTime即表示其局部时间坐标系的原点与父的局部时间坐标系的原点的偏移。

4、layer的局部时间的转换。layer提供converTime方法将时间从layer的局部时间坐标系之间转换。特别地,想将一个全局时间转换到某个layer的局部时间,可以这样获得:[layer convertTime:time fromLayer:nil](可以这样理解,当fromLayer参数为nil是,即表示time参数为全局时间)。

5、Core Animation使用全局时间与layer、animation的局部时间的方式。有几个重要的点:

- 全局时间和animation的局部时间。Core Animation通过使用全局时间的当前时间在animation的局部时间坐标系的位置来决定对animation的操作的。

== 当前时间在animation的局部时间坐标系为负数,表示动画还未开始。

== 当前时间在animation的局部时间坐标系为正数,而且在duration范围内,就会根据在animation的局部时间坐标系的位置来得到animation property的插值,然后用这个新的值去更新渲染树。

== 当前时间在animation的局部时间坐标系为正数,而且在duration范围外,表示动画已经结束了。

== layer的speed为0时,layer的动画全部暂停。

6、“相对”的强大之处。当父的beginTime改变时,所有的子的局部时间坐标系也就相应改变了(坐标系的原点改变了)。这个“相对”机制,再加上对Core Animation使用全局时间与layer、animation的局部时间的方式的了解,我们就可以很好的理解“动画的暂停与继续的实现原理”和“AVSynchronizedLayer的实现原理“等。关键点就是:通过更改layer的beginTime,从而使layer的动画的局部坐标系改变,从而使得“当前时间”处于animation的局部时间坐标系的合适的位置!!

7、举例说明。

- layer1(beginTime=0) -> animation1(beginTime=0,duration=5)。

animation1在layer1被commited后,其beginTime=CACurrentMediaTime()。因此,animation1马上开始执行。

- layer1(beginTime=0) -> animation1(beginTime=0,duration=5) -> animation2(beginTime=0, duration=2)。

animation1在layer1被commited后,其beginTime=CACurrentMediaTime()。因此,animation1马上开始执行;animation2的beginTime为0,但animation2不是“根animation”,beginTime还是为0,对animation1的局部时间坐标系偏移为0,因此,animation2与animation1同时开始执行。

- layer1(beginTime=0) -> animation1(beginTime=0,duration=5) -> animation2(beginTime=1, duration=2)。

animation1在layer1被commited后,其beginTime=CACurrentMediaTime()。因此,animation1马上开始执行;animation2的beginTime为1,对animation1的局部时间坐标系偏移为1,因此,animation2比animation1晚1秒开始执行。

- layer1(beginTime=0) -> animation1(beginTime=CACurrentMediaTime()+2,duration=5)

animation1在layer1被commited后,animation1会在2秒后开始执行。

- layer1(beginTime=0) -> animation1(beginTime=CACurrentMediaTime()-2,duration=5)

animation1在layer1被commited后,animation1会以其2秒处的状态开始执行(相当与已经运行了2秒),并且运行3秒后完成动画。

- layer1(beginTime=0) -> animation1(beginTime=AVCoreAnimationBeginTimeAtZero,duration=5) -> animation2(beginTime=1, duration=2)。

layer1被commited后,animation1和animation2都不会执行。因为对于当前时间,animation1和animation2已经结束了。因为,一般来说,当前时间CACurrentMediaTime()是一个很大的值。

- layer1(beginTime=0) -> layer2(beginTime=10) 

CFTimeInterval currentTime = CACurrentMediaTime();

CFTimeInterval timeLayer1 = [layer1 convertTime:currentTime fromLayer:nil]; // timeLayer1 == currentTime

CFTimeInterval timeLayer2 = [layer2 convertTime:currentTime fromLayer:nil]; // timeLayer2 == (currentTime - 10)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值