版本记录
版本号 | 时间 |
---|---|
V1.0 | 2017.12.03 |
前言
app中好的炫的动画可以让用户耳目一新,为产品增色不少,关于动画的实现我们可以用基本动画、关键帧动画、序列帧动画以及基于CoreGraphic的动画等等,接下来这几篇我就介绍下我可以想到的几种动画绘制方法。感兴趣的可以看我写的另外几篇。
1. 实现动画方式深度解析(一) —— 播放GIF动画(一)
2. 实现动画方式深度解析(二) —— 播放GIF动画之框架FLAnimatedImage的使用(二)
3. 实现动画方式深度解析(三) —— 播放序列帧动画(一)
4. 实现动画方式深度解析(四) —— QuartzCore框架(一)
5. 实现动画方式深度解析(五) —— QuartzCore框架之CoreAnimation(二)
6. 实现动画方式深度解析(六) —— Core Animation Basics(三)
7. 实现动画方式深度解析(七) —— Core Animation之Setting Up Layer Objects(四)
8. 实现动画方式深度解析(八) —— Core Animation之动画层内容 (五)
9. 实现动画方式深度解析(九) —— Core Animation之构建图层层级 (六)
10. 实现动画方式深度解析(十) —— Core Animation之高级动画技巧 (七)
11. 实现动画方式深度解析(十一) —— Core Animation之更改图层的默认行为(八)
12. 实现动画方式深度解析(十二) —— Core Animation之提高动画的性能(九)
13. 实现动画方式深度解析(十三) —— Core Animation之图层样式属性动画(十)
14. 实现动画方式深度解析(十四) —— Core Animation之 KVC 扩展(十一)
15. 实现动画方式深度解析(十五) —— Core Animation之可动画属性 (十二)
16. 实现动画方式深度解析(十六) —— Core Animation之CABasicAnimation动画示例 (十三)
17. 实现动画方式深度解析(十七) —— Core Animation之CAKeyframeAnimation动画示例 (十四)
18. 实现动画方式深度解析(十八) —— UIView动画 (一)
19. 实现动画方式深度解析(十九) —— Lottie - iOS动画 (一)
20. 实现动画方式深度解析(二十) —— Lottie - iOS动画之示例分享 (二)
21. 实现动画方式深度解析(二十一) —— Keyframes动画之框架基本 (一)
22. 实现动画方式深度解析(二十二) —— Keyframes动画之简单示例(二)
23. 实现动画方式深度解析(二十三) —— CoreGraphic动画(一)
24. 实现动画方式深度解析(二十四) —— CoreAnimation框架CADisplay动画之一个简单示例(一)
CADisplayLink类
CADisplayLink
是一个计时器对象,允许您的应用程序将其绘图与显示器的刷新率同步。
您的应用程序将初始化一个新的display link
,提供一个目标对象和一个在屏幕更新时调用的方法。要使显示循环与显示同步,应用程序会使用addToRunLoop:forMode:
方法将其添加到运行循环中
一旦display link
与运行循环相关联,当屏幕的内容需要更新时,目标上的选择器被调用。目标可以读取display link
的时间戳属性来检索前一帧显示的时间。例如,显示电影的应用程序可能会使用时间戳来计算下一个要显示的视频帧。执行自己的动画的应用程序可能会使用时间戳来确定显示的对象在即将到来的帧中的显示位置和方式。
duration
属性提供了在maximumFramesPerSecond
帧之间的时间量。要计算实际的帧持续时间,请使用targetTimestamp - timestamp
。您可以在应用程序中使用实际的帧持续时间来计算显示器的帧速率,下一帧将显示的大致时间,并调整绘制行为,以便及时准备下一帧以显示。
您的应用程序可以通过将paused
属性设置为YES来禁用通知。此外,如果您的应用程序无法在所提供的时间内提供帧,您可能需要选择较慢的帧速率。与跳过帧的应用程序相比,具有较慢但一致帧频的应用程序对用户来说会更平滑。您可以通过设置preferredFramesPerSecond
属性来定义每秒的帧数。
当应用程序使用display link
完成时,应该调用invalidate
将其从所有运行循环中删除,并将其从目标中解除关联。
CADisplayLink不应被分类。
Topics
1. Creating Instances
-
+displayLinkWithTarget:selector:
- 返回新的
display link
对象。
- 返回新的
2. Scheduling the Display Link to Send Notifications
-
-addToRunLoop:forMode:
- 用运行循环注册
display link
。
- 用运行循环注册
-
-removeFromRunLoop:forMode:
- 从给定模式的运行循环中删除
display link
。
- 从给定模式的运行循环中删除
-
-invalidate
- 从所有运行循环模式中删除
display link
。
- 从所有运行循环模式中删除
3. Configuring the Display Link
-
duration
- 屏幕刷新更新之间的时间间隔。
-
preferredFramesPerSecond
-
display link
用来通知目标的帧频。
-
-
frameInterval
- 在
display link
通知目标之前,必须通过的帧数。
- 在
-
paused
- 一个布尔值,指出
display link
对目标的通知是否被挂起。
- 一个布尔值,指出
-
timestamp
- 与显示的最后一帧关联的时间值。
-
targetTimestamp
- 与显示的下一帧关联的时间值。
4. Inherits From
NSObject
一个例子
下面我们就看一个简单的例子。
1. ViewController.m
#import "ViewController.h"
#import "JJJumpVC.h"
@interface ViewController ()
@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) CADisplayLink *displayLink;
@end
@implementation ViewController
#pragma mark - Override Base Function
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor lightGrayColor];
self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 100.0, 100.0, 100.0)];
self.imageView.backgroundColor = [UIColor redColor];
self.imageView.userInteractionEnabled = YES;
[self.view addSubview:self.imageView];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageViewDidTapped:)];
[self.imageView addGestureRecognizer:tapGesture];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.backgroundColor = [UIColor blueColor];
[button addTarget:self action:@selector(buttonDidClick:) forControlEvents:UIControlEventTouchUpInside];
button.frame = CGRectMake(0.0, 100.0, self.view.bounds.size.width, 40.0);
[self.view addSubview:button];
CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(startAnimation)];
if ([[UIDevice currentDevice].systemVersion floatValue] < 10.0) {
displayLink.frameInterval = 60/20;
}
else {
displayLink.preferredFramesPerSecond = 60/20;
}
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
self.displayLink = displayLink;
}
#pragma mark - Object Private Function
- (void)startAnimation
{
CGFloat margin = (700 - 100) / 20;
self.imageView.frame = CGRectMake(self.imageView.frame.origin.x, self.imageView.frame.origin.y + margin, 100.0, 100.0);
if (self.imageView.frame.origin.y == 700) {
[self.displayLink invalidate];
self.displayLink = nil;
}
}
#pragma mark - Action && Notification
- (void)imageViewDidTapped:(UITapGestureRecognizer *)tapGesture
{
NSLog(@"我是被点击了吗");
}
- (void)buttonDidClick:(UIButton *)button
{
JJJumpVC *jumpVC = [[JJJumpVC alloc] init];
[self.navigationController pushViewController:jumpVC animated:YES];
}
@end
下面我们看输出和效果示意图。
2017-12-03 20:53:51.411331+0800 JJDisplayAnmation_demo5[5533:238157] 我是被点击了吗
2017-12-03 20:53:51.865861+0800 JJDisplayAnmation_demo5[5533:238157] 我是被点击了吗
2017-12-03 20:53:52.344815+0800 JJDisplayAnmation_demo5[5533:238157] 我是被点击了吗
2017-12-03 20:53:52.512871+0800 JJDisplayAnmation_demo5[5533:238157] 我是被点击了吗
2017-12-03 20:53:53.001698+0800 JJDisplayAnmation_demo5[5533:238157] 我是被点击了吗
2017-12-03 20:53:53.444368+0800 JJDisplayAnmation_demo5[5533:238157] 我是被点击了吗
2017-12-03 20:53:53.899680+0800 JJDisplayAnmation_demo5[5533:238157] 我是被点击了吗
2017-12-03 20:53:54.361407+0800 JJDisplayAnmation_demo5[5533:238157] 我是被点击了吗
2017-12-03 20:53:54.561303+0800 JJDisplayAnmation_demo5[5533:238157] 我是被点击了吗
2017-12-03 20:53:54.744800+0800 JJDisplayAnmation_demo5[5533:238157] 我是被点击了吗
2017-12-03 20:53:55.293545+0800 JJDisplayAnmation_demo5[5533:238157] 我是被点击了吗
2017-12-03 20:53:56.163031+0800 JJDisplayAnmation_demo5[5533:238157] 我是被点击了吗
2017-12-03 20:53:56.355348+0800 JJDisplayAnmation_demo5[5533:238157] 我是被点击了吗
2017-12-03 20:53:56.524072+0800 JJDisplayAnmation_demo5[5533:238157] 我是被点击了吗
下面看一下效果图。
用CADisplayLink
做动画有两个优点:
1)控件可以在运动的过程中响应点击事件。
2)跳转到别的界面pop回来后,动画不会消失,仍在继续。
感兴趣的可以看DemoGitHub - 刀客传奇
后记
未完,待续~~~