iOS 动画效果:Core Animation & Facebook's pop
本文转载至 http://www.cocoachina.com/ios/20151223/14739.html
感谢原创作者分享
前言
相信很多人对实现 iOS 中的动画效果都特别头疼,往往懒得动手,功能实现不就得了,何必要那么花哨、装13的东西。但是看到别人的炫酷动效,心中又瘙痒不已,便下定决心学习,于是开始翻看 Core Animation、UIView动画(其实是对Core Animation的一种封装)相关资料。不小心看到一群大神正在热烈讨论,钻一进去一看,原来是 POP(潜意识:Facebook出品必属精品),这还学什么Core Animation,果断pod一个来玩玩,于是你就左手CA,右手 POP 开森地把玩起来了。
此时,你可能已经学会了CA的基本使用方法,也对UIView动画的便捷感到惊喜,但是不满足的你,显然有更高的追求,POP 以其灵活的用法,丰富的动效,完整的API文档,深得很多程序员的喜爱。作为一个有逼格的程序员,这么流行的框架,必然是值得深入学习的,但是你是否考虑过这样的第三方动画框架是否存在什么不足。因此,作为一个有追求的程序员,有必要来稍微深入地探讨一下 Core Animation 和 POP 不同点。
Core Animation 工作机制
首先我们需要了解CA是如何工作的。每当我们创建并添加动画到 layer 时,QuartzCore 框架就会把动画的参数打包好,然后通过 IPC (处理器)发送给名为 backboardd 的后台处理程序。你的应用也会发送当前展示在屏幕上的每一个 layer 的信息。
backboardd 会处理 layer 的结构体系然后通过 OpenGL 绘制出来。它还会处理你已经添加过的动画(也可以是视图,因为视图本质是包裹着 layer的)。你一定要理解的是,backboardd 使得动画的每一帧都可以在你的应用中完全独立。这里唯一的回调是动画的开始和结束(详见CAAnimationDelegate 协议)。你的应用完全不会参与动画的绘制,这些绘制完全独立于你的应用进程(除非你明确地在你的应用中通过动画通用属性要求绘制动画帧)。这意味着你可以继续在主线程做其他事情,并且不会影响到 CAAnimation 的性能。如果你阻塞了你的主线程,或者你在调试器中暂停了你的程序,你的动画还是会继续执行。
但是你可能会有这样的疑问:每个 CALayer 不是还有一个 presentationLayer 属性吗?
presentationLayer的官方解释:
“While an animation is in progress, you can retrieve this object and use it to get the current values for those animations.”
当CAAnimation发生时,你在屏幕上看到的实际上是 presentation layer 的改变。如果你访问 presentation layer,QuartzCore 将会计算现有的帧状态,并且使用这个帧状态去构建 presentation layer 对象。因为动画状态在动画执行期间一直处于改变,因此你将会获得近似值。
POP 工作机制
现在有很多优秀的第三方动画库,POP 因为其使用灵活、功能强大、文档齐全,所以备受好评,先看一下官方介绍:
POP是一个在iOS与OS X上通用的极具扩展性的动画引擎 它在基本的静态动画的基础上增加的弹簧动画与衰减动画。
使之能创造出更真实更具物理性的交互动画 POP的API可以快速的与现有的ObjC代码集成并可以作用于任意对象的任意属性。
POP是个相当成熟且久经考验的框架 Facebook出品的令人惊叹的Paper应用中的所有动画和效果即出自POP。
更为详细的介绍和使用请查看官方文档以及里脊串的 POP介绍与使用实践(快速上手动画)。
POP 本质上是基于定时器的动画库,使用每秒 60 频率的定时器,即时钟频率为 1/60 秒(为了匹配 iOS 显示屏帧率),使得动画刷新绘制频率与屏幕刷新频率一致。很多这类动画库都使用 CADisplayLink 做为一个回调源。
一旦定时器刷新,动画库计算动画的进程,这意味着动画库会计算那些活动的东西的状态(通常是layer 属性,如 bound,opactiy,transform 等)。然后动画库提供最新计算的值给有动画的 layer (或者其他对象)。最主要的区别是,layer 的状态将会在这种情况下改变。
由于 layer 的一些参数已经被改变,你的应用必须通过 IPC 通知 backboardd 处理这些变化。当 backboardd 接收到变化通知(同时接收到的还有应用中的 layer 树),它将在屏幕上重绘一切东西。这意味着,你应用中做的每一个动画帧都会传送数据到 backboardd (即通知 backboardd ),因为 backboardd 完全不知道 layer 发生了什么事情。综上,你的应用就是在这种情况下运行动画的。
Core Animation 和 POP 运行动画对比
由于 POP 是基于定时器定时刷新添加动画的原理,那么如果将动画库运行在主线程上,会由于线程阻塞的问题导致动画效果出现卡顿、不流畅的情况。更为关键的是,你不能将动画效果放在子线程,因为你不能将对 view 和 layer 的操作放到主线程之外。
为了验证上述的观点,我做了一个实验,首先用CA动画制作一个可以旋转的 view:
1
2
3
4
5
6
7
8
|
UIView *viewCA = [[UIView alloc]initWithFrame:CGRectMake(50,50, 100, 100)]; viewCA.backgroundColor = [UIColor blueColor]; [self.view addSubview:viewCA]; CABasicAnimation *caAnimation = [CABasicAnimation animationWithKeyPath:@ "transform.rotation.z" ]; caAnimation.toValue = @(M_PI); caAnimation.duration = 2.0; caAnimation.repeatCount = 500; [viewCA.layer addAnimation:caAnimation forKey:@ "anim" ]; |
再创建一个利用 POP 动画库制作的可旋转 view:
1
2
3
4
5
6
7
8
9
|
UIView *viewPOP = [[UIView alloc]initWithFrame: CGRectMake(CGRectGetWidth(self.view.bounds) - 100 - 50, 50, 100, 100)]; viewPOP.backgroundColor = [UIColor yellowColor]; [self.view addSubview:viewPOP]; POPBasicAnimation *popAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerRotation]; popAnimation.toValue = @(M_PI); popAnimation.duration = 2.0; popAnimation.repeatCount = 500; [viewPOP.layer pop_addAnimation:popAnimation forKey:@ "rotation" ]; |
在没有线程阻塞的情况下,对比两个动画库的运行效果如下:
可以看出来虽然在没有线程阻塞,但是 POP 的动画在结束时有一个明显的停止动作,是因为 POP 的动画效果不好吗?
答案是 timingFunction
CoreAnimation 和 POPBasicAnimation提供同样的五种 timingFunction:
kCAMediaTimingFunctionLinear
kCAMediaTimingFunctionEaseIn
kCAMediaTimingFunctionEaseOut
kCAMediaTimingFunctionEaseInEaseOut
kCAMediaTimingFunctionDefault
重点说一下:kCAMediaTimingFunctionDefault(引自:iOS-Core-Animation-Advanced-Techniques(五))
它和kCAMediaTimingFunctionEaseInEaseOut很类似,但是加速和减速的过程都稍微有些慢。它和kCAMediaTimingFunctionEaseInEaseOut的区别很难察觉,可能是苹果觉得它对于隐式动画来说更适合(然后对UIKit就改变了想法,而是使用kCAMediaTimingFunctionEaseInEaseOut作为默认效果),虽然它的名字说是默认的,但还是要记住当创建显式的CAAnimation它并不是默认选项(换句话说,默认的图层行为动画用kCAMediaTimingFunctionDefault作为它们的计时方法)。
如果不设置 timingFunction 属性,那么在使用 CA 的情况下, timingFunction 是kCAMediaTimingFunctionLinear 的,而 POP 却是kCAMediaTimingFunctionEaseOut ,因此我们只要添加这么一行代码:
1
|
popAnimation.timingFunction?=?[CAMediaTimingFunction?functionWithName:kCAMediaTimingFunctionLinear]; |
现在再看效果:
可以看出来,在主线程没有阻塞的情况下,两种动画库的表现并无差异。
现在我们来制造一点难度,人工利用线程的 sleep 增加一个主线程阻塞:
1
2
3
4
5
6
|
- (void)repeatedlyBlockMainThread { NSLog(@ "blocking main thread!" ); [NSThread sleepForTimeInterval:0.25]; [self performSelector:@selector(repeatedlyBlockMainThread) withObject:nil afterDelay:1]; } |
然后再 viewDidLoad 里面调用 :
1
|
[self performSelector:@selector(repeatedlyBlockMainThread) withObject:nil afterDelay:1]; |
现在再来看一下两者的动画效果:
很明显,我们可以看出来,由于添加了主线程阻塞,利用 POP 制作的动画视图,在每隔 1s 都会卡顿一下,而 CA 的视图却完全不受主线程阻塞的影响。
总结
通过这次简单的对比,我们从工作机制上了解了 CA 和 POP 两个动画库的基本原理,并用简单的动画效果对比,重现了在主线程阻塞的情况下两者的差异,很显然, POP 受主线程阻塞的影响很大,在使用过程中,应避免在有可能发生主线程阻塞的情况下使用 POP ,避免制作卡顿的动画效果,产生不好的用户体验。文中提出了 POP 的这种缺点,但是 POP 毕竟是久经考验的动画技术,本人也正在学习中,有错误的地方吝请指正。
对比系列,是个人比较喜欢的一种学习方式,通过对比,找出不同技术的优缺点,可以更合理地使用这些武器,俗话说:好钢用在刀刃上,大抵如此。
iOS 动画效果:Core Animation & Facebook's pop的更多相关文章
- IOS动画(Core Animation)总结 (参考多方文章)
一.简介 iOS 动画主要是指Core Animation框架.官方使用文档地址为:Core Animation Guide. Core Animation是IOS和OS X平台上负责图形渲染与动画的 ...
- iOS之核心动画(Core Animation)
Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍.也就是说,使用少量的代码就可以实现非常强大的功能. Core ...
- IOS 核心动画(Core Animation)
Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,使用它 能做出非常炫丽的动画效果,而且往往是事半功倍.也就是说,使用少量的代码就 可以实现非常强大的功能. Core ...
- iOS Instruments之Core Animation动画性能调优(工具复选框选项介绍)
Core Animation工具用来监测Core Animation性能.它给我们提供了周期性的FPS,并且考虑到了发生在程序之外的动画(见图12.4) Core Animation工具提供了一系列复 ...
- iOS动画效果和实现
动画效果提供了状态或页面转换时流畅的用户体验,在iOS系统中,咱们不需要自己编写绘制动画的代码,Core Animation提供了丰富的api来实现你需要的动画效果. UIKit只用UIView来展示 ...
- iOS开发之Core Animation
在IOS中如果使用普通的动画则可以使用UIKit提供的动画方式来实现,如果想实现更复杂的效果,则需要使用Core Animation了. 在Core Animation中我们经常使用的是 CABasi ...
- ios 动画效果CATransition笔记
初学ios开发,很多概念还不清楚,所以只有边学边做例子.又怕学了后面忘了前面,因此用自己的博客来纪录自己的学习历程,也是对自己学习不要懈怠做个监督. 刚学ios做动画效果.因为ios封装得很好,实现i ...
- AndroidUI 视图动画-自定义动画效果 (Animation)
如果Android提供的四种动画 效果 和混合动画效果 不能够 满足需求的话,可以使用自定义动画效果 : 新建一个类CustomAnimation 使其继承自 android.view.animati ...
- CSS动画效果之animation
Y(^o^)Y css动画大乱弹之animation. 概述 什么是animation呢?在回答这个问题之前,先要说明什么叫做@keyframe(关键帧).@keyframe算是一个动画模板.在其中, ...
随机推荐
- Oracle system表空间满的暂定解决方法
Oracle system表空间满的暂定解决方法 数据库用的是Oracle Express 10.2版本的.利用Oracle Text做全文检索应用,创建用户yxl时没有初始化默认表空间,在系统开发过 ...
- 高通 mixer_paths.xml 音频配置文件 初始化过程
记录一下高通音频配置文件mixer_paths.xml初始化过程.参考代码基于Android O. hardware/qcom/audio/hal/audio_hw.c struct audio_mo ...
- Spring Data Commons 官方文档学习
Spring Data Commons 官方文档学习 -by LarryZeal Version 1.12.6.Release, 2017-07-27 为知笔记版本在这里,带格式. Table o ...
- Going deeper with convolutions 这篇论文
致网友:如果你不小心检索到了这篇文章,请不要看,因为很烂.写下来用于作为我的笔记. 2014年,在LSVRC14(large-Scale Visual Recognition Challenge)中, ...
- Visual Studio主题与配色方案
有个性的开发人员总是喜欢使用属于的主题和配色方案,它们可以看出开发者的个性,更改它们可以缓解审美疲劳,总之选择一个适合自己的解决方案可能极大的增加自己的编码舒适度. 配色方案的选择和使用 手动修改Vi ...
- Lombok简化Java代码的好工具
lombok 的官方网址:http://projectlombok.org/ 关于lombok 的介绍,有几篇帖子,写得都很好 比如 http://www.blogjava.net/fancydeep ...
- Linux系统date时间设定
修改linux系统的时间EDT和EST为CST EDT:指美国东部夏令时间 EST:英国时间 CST:北京时间 那么现在只要改成北京时间的时区CST就可以了,修改如下: [root@localhost ...
- Python自然语言处理学习——jieba分词
jieba——“结巴”中文分词是sunjunyi开发的一款Python中文分词组件,可以在Github上查看jieba项目. 要使用jieba中文分词,首先需要安装jieba中文分词,作者给出了如下的 ...
- iPhone 配置使用工具
“iPhone 配置实用工具”可让您轻松地创建.维护和安装配置描述文件及对配置描述文件进行加密,跟踪和安装预置描述文件与授权的应用程序,以及采集包括控制台日志在内的设备信息. http://suppo ...
- 184使用 Core Image 框架处理照片
实现图片的老旧.色彩.旋转效果 (1)使用 StoryBoard 故事版布局界面: (2)使用 Core Image 框架的 CIFilter 过滤器:分别对应的过滤器名称是:CISepiaTone( ...