屏幕刷新动画-CADisplayLink
CADisplayLink
是一定时器对象,相对NSTimer
的不同之处在于,CADisplayLink
是根据屏幕的刷新频率来实现的一个定时器。iOS设备是每秒刷新60次,意味着CADisplayLink
开启后,每秒也将执行60次。CADisplayLink
的selector
调用时机是在屏幕刷新结束后。
CADisplayLink与NSTimer区别
-
CADisplayLink
是屏幕刷新结束后调用的,相对于NSTimer
来说精度更高,因为在RunLoop
出现阻塞的情况下NSTimer
的精度有所下降。主要跟RunLoop
的周期有关。 -
CADisplayLink
是基于屏幕刷新的,更适合做UI不停绘制的工作。
CADisplayLink常用属性
//上一帧的时间
@property(readonly, nonatomic) CFTimeInterval timestamp;
//屏幕时两帧之间的时间间隔
@property(readonly, nonatomic) CFTimeInterval duration;
//下一帧的时间
@property(readonly, nonatomic) CFTimeInterval targetTimestamp;
//是否暂停
@property(getter=isPaused, nonatomic) BOOL paused;
//已过时
@property(nonatomic) NSInteger frameInterval;
//每秒多少帧
@property(nonatomic) NSInteger preferredFramesPerSecond;
创建CADisplayLink
通过调用CADisplayLink
的displayLinkWithTarget可以创建一个CADisplayLink
对象,然后再通过调用addToRunLoop
将定时器添加到runloop
中启动定时器,可以设置preferredFramesPerSecond
来指定每秒执行多少次。
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateTimer)];
//每秒执行一次
self.displayLink.preferredFramesPerSecond = 1;
[self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
CADisplayLink示例
下面通过使用CADisplayLink
和CAShapeLayer
来实现一个圆形进度条的动画。
- 首先用
CAShapeLayer
和UIBezierPath
来创建一个灰色的圆形作为背景,如下所示:
CGPoint point = CGPointMake(self.animationView.frame.size.width/2, self.animationView.frame.size.height/2);
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:point radius:80 startAngle:0 endAngle:360 clockwise:YES];
CAShapeLayer *layer = [CAShapeLayer layer];
layer.lineWidth = 5;
layer.strokeColor = [UIColor grayColor].CGColor;
layer.fillColor = nil;
layer.path = path.CGPath;
[self.animationView.layer addSublayer:layer];
- 同理再创建一个用于显示动画的红色圆形,如下所示:
CAShapeLayer *layer = [CAShapeLayer layer];
layer.lineWidth = 5;
layer.strokeColor = [UIColor redColor].CGColor;
layer.fillColor = nil;
[self.animationView.layer addSublayer:layer];
self.progressLayer = layer;
- 调用
CADisplayLink
的回调不停的添加弧度,如下所示:
-(void)updateTimer{
if(self.startAngle >= 360){
self.displayLink.paused = YES;
}
CGPoint point = CGPointMake(self.animationView.frame.size.width/2, self.animationView.frame.size.height/2);
[self.progressPath addArcWithCenter:point radius:80 startAngle:(M_PI /180.0) *_startAngle endAngle:(M_PI /180.0) *(_startAngle + 3.6) clockwise:YES];
self.progressLayer.path = self.progressPath.CGPath;
self.startAngle += 3.6;
}