最近想开始学动画 听说 FaceBook 的 Pop动画 不错 所以最近学习下
Pop
使用指南
Pop Animation
在使用上和Core Animation很相似,都涉及到Animation
的载体概念,不同的是Core Animation
的载体只能是CALayer
,而Pop animation
可以是任意基于NSObject
的对象.当然大多数情况Anima
当听闻Facebook
要开源自己的Animation
框架的时候,我还以为是基于Core Animation
进行的封装、包含了一些动画效果库.等源码真正出来后,才发现完全想错了,Facebook Pop
其实是基于CADisplayLink
(Mac平台上使用的CVDisplayLink
)实现的独立于Core Animation
之外的动画方案.
CADisplayLink
什么是CADisplayLink
CADisplaylink
是一个能让我们以和屏幕刷新率相同的频率将内容画到屏幕上的定时器。我们在应用中创建一个新的CADisplayLink
对象,把它添加到一个runloop
中,并给它提供一个target
和 selector
在屏幕刷新的时候调用.
一但 CADisplaylink
以特定的模式注册到 runloop
之后,每当屏幕需要刷新的时候,runloop
就会调用CADisplayLink
绑定的target
上的selector
,这时 target
可以读到CADisplaylink
的每次调用时间戳,用来准备下一帧显示需要的数据。例如一个视屏应用时间戳来计算下一帧要显示的视屏数据。在ui做动画的过程中,需要通过时间戳来计算UI对象在动画的下一帧要更新的大小等等。
在添加进runloop
的时候我们应该选用高一些的优先级,来保证动画的平滑。可以设想一下,我们在动画的过程中,runloop
被添加进来了一个高优先级的任务,那么,下一次的调用就会被暂停转而先去执行高优先级的任务,然后再接着执行CADisplayLink
的调用,从而造成动画过程中的卡顿,使动画不流畅。
duration
属性提供了每帧之间的时间,也就是屏幕每次刷新之间的时间。我们可以使用这个时间来计算下一帧要显示的UI的数值。但是 duration
只是个大概的时间,如果CPU忙于其它计算,就没法保证以相同的频率执行屏幕的绘制操作,这样会跳过几次调用回调方法的机会。
frameIntereval
属性是可读可写的NSInterger
型值,标识间隔多少帧调用一次selector
方法,默认值是1,即每帧都调用一次。如果每帧都调用一次的话,对于ios设备来说那刷新频率就是60HZ也就是每秒60次,如果将frameIntereval
设为2那么就会两帧调用一次也就是变成了每秒刷新30次。
我们通过pause
属性开控制CADisplayLink
的运行。当我们想结束一个CADisplayLink
的时候,应该代用-(void)invalidate
从runloop
中删除并删除之前绑定的target
根selector
另外 CADisplayLink
不能贝继承。
CADisplayLink 与 NSTimer 有什么不同
ios设备的屏幕刷新频率是固定的,CADisplayLink
在正常情况下会在每次刷新结束都被调用,精确度相当高。
NSTimer
的精确度就显得低了点,比如NSTimer
的触发时间到的时候,runloop
如果在阻塞状态,出发时间就会推迟到下一个runloop
周期。并且NStimer
新增了tolerance
属性,让用户可以设置可以容忍的触发的时间的延迟范围
CadisplayLink
使用场合相对专一,适合UI的不停重绘,比如自定义动画引擎或者视屏播放的渲染。NSTimer
的使用范围要广泛的多,各种需要单词或者循环定时处理的任务都可以使用。在UI相关的动画或者显示内容使用 CADisplayLink 比起用 NSTimer 的好处就是我们不需要格外关心屏幕的刷新频率了,因为它本身就是跟着屏幕刷新同步的。
CADisplayLink使用的例子
self.displayLink=[CADisplayLink displayLinkWithTarget:self selector:@selector(updateTextColor)];
self.displayLink.paused=YES;
[self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
-(void)updateTextColor
{
}
-(void)startAnimation
{
self.beginTime=CACurrentMediaTime();
self.displayLink.paused = NO;
}
-(void)stopAnimation
{
self.displayLink.paused = YES;
[self.displayLink invalidate];
self.displayLink = nil;
}
网友评论