Core-Animation-Advanced-Techniqu

2017-03-12  本文已影响100人  西山薄凉

很棒的翻译!
Git传送门:https://github.com/AttackOnDobby/iOS-Core-Animation-Advanced-Techniques

图层树

摘要:这一章阐述了图层的树状结构,说明了如何在iOS中由UIView的层级关系形成的一种平行的CALayer层级关系,在后面的实验中,我们创建了自己的CALayer,并把它添加到图层树中。
Core Animation是一个复合引擎,它的职责就是尽可能快地组合屏幕上不同的可视内容,这个内容是被分解成独立的图层,存储在一个叫做图层树的体系之中。
UIView<--->CALayer
视图----------图层
视图层级-----图层树
功能不同点:和UIView最大的不同是CALayer不处理用户的交互。
但是为什么iOS要基于UIView和CALayer提供两个平行的层级关系呢?为什么不用一个简单的层级来处理所有事情呢?原因在于要做职责分离,这样也能避免很多重复代码。

寄宿图

摘要:本章介绍了寄宿图和一些相关的属性。你学到了如何显示和放置图片, 使用拼合技术来显示, 以及用CALayerDelegate和Core Graphics来绘制图层内容。

CALayer相关属性

  1. 点(逻辑像素)
  2. 像素(物理像素)
  3. 单位(在openGL中会比较常用)

图层几何学

摘要:本章涉及了CALayer的集合结构,包括它的frame,position和bounds,介绍了三维空间内图层的概念,以及如何在独立的图层内响应事件,最后简单说明了在iOS平台,Core Animation对自动调整和自动布局支持的缺乏。

  1. UIView有三个比较重要的布局属性:frame,bounds和center,CALayer对应地叫做frame,bounds和position。
  2. frame代表了图层的外部坐标(也就是在父图层上占据的空间),bounds是内部坐标({0, 0}通常是图层的左上角),center和position都代表了相对于父图层anchorPoint所在的位置。
  3. 视图的frame,bounds和center属性仅仅是存取方法,当操纵视图的frame,实际上是在改变位于视图下方CALayer的frame,不能够独立于图层之外改变视图的frame。
  4. 对于视图或者图层来说,frame并不是一个非常清晰的属性,它其实是一个虚拟属性,是根据bounds,position和transform计算而来,所以当其中任何一个值发生改变,frame都会变化。相反,改变frame的值同样会影响到他们当中的值。
  1. 和视图一样,图层在图层树当中也是相对于父图层按层级关系放置,一个图层的position依赖于它父图层的bounds,如果父图层发生了移动,它的所有子图层也会跟着移动。
  2. CALayer提供一组Api可以方便的转换图层之间的点或矩形。
  3. 翻转的几何结构:常规说来,在iOS上,一个图层的position位于父图层的左上角,但是在Mac OS上,通常是位于左下角。Core Animation可以通过geometryFlipped属性来适配这两种情况,它决定了一个图层的坐标是否相对于父图层垂直翻转。
  4. Z轴:CALayer存在于一个三维空间当中,CALayer还有另外两个属性,zPosition和anchorPointZ。
  5. HitTest:CALayer并不关心任何响应链事件,所以不能直接处理触摸事件或者手势。但是它有一系列的方法帮你处理事件:-containsPoint:和-hitTest:。

视觉效果

摘要:这一章介绍了一些可以通过代码应用到图层上的视觉效果,比如圆角,阴影和蒙板。我们也了解了拉伸过滤器和组透明。

变换

摘要:这一章涉及了一些2D和3D的变换。你学习了一些矩阵计算的基础,以及如何用Core Animation创建3D场景。你看到了图层背后到底是如何呈现的,并且知道了不能把扁平的图片做成真实的立体效果,最后我们用demo说明了触摸事件的处理,视图中图层添加的层级顺序会比屏幕上显示的顺序更有意义。

专用图层

摘要:本章将会介绍其他的一些图层类,进一步扩展使用Core Animation绘图的能力。

隐式动画

摘要:这一章讨论了隐式动画,还有Core Animation对指定属性选择合适的动画行为的机制。同时你知道了UIKit是如何充分利用Core Animation的隐式动画机制来强化它的显示系统,以及动画是如何被默认禁用并且当需要的时候启用的。最后,你了解了呈现和模型图层,以及Core Animation是如何通过它们来判断出图层当前位置以及将要到达的位置。

显式动画

摘要:这一章中,我们涉及了属性动画(你可以对单独的图层属性动画有更加具体的控制),动画组(把多个属性动画组合成一个独立单元)以及过度(影响整个图层,可以用来对图层的任何内容做任何类型的动画,包括子图层的添加和移除)。

  1. 基础动画:fromValue、toValue、byValue(id类型),CAAnimationDelegate
  2. 关键帧动画: rotationMode参数,虚拟属性(transform)。
  3. 动画组
  4. 过渡:属性动画只对图层的可动画属性起作用,所以如果要改变一个不能动画的属性(比如图片),或者从层级关系中添加或者移除图层,属性动画将不起作用。过渡动画首先展示之前的图层外观,然后通过一个交换过渡到新的外观。CATransition的type及subtype属性。隐式过渡、图层树动画。自定义动画。

图层时间

摘要:在这一章,我们了解了CAMediaTiming协议,以及Core Animation用来操作时间控制动画的机制。在下一章,我们将要接触缓冲,另一个用来使动画更加真实的操作时间的技术。

  1. 持续和重复
  2. 相对时间:beginTime、speed、timeOffSet
  3. fillMode
  1. 全局时间和本地时间:CALayer像hitTest一样提供了方法来转换不同图层间的本地时间。
  2. 暂停、倒回、快进:layer.speed。
  3. 手动动画

缓冲

摘要: 在这一章中,我们了解了有关缓冲和CAMediaTimingFunction类,它可以允许我们创建自定义的缓冲函数来完善我们的动画,同样了解了如何用CAKeyframeAnimation来避开CAMediaTimingFunction的限制,创建完全自定义的缓冲函数。

  1. 三次贝塞尔曲线:CAMediaTimingFunction函数的主要原则在于它把输入的时间转换成起点和终点之间成比例的改变。起点、终点、两个控制点。
  2. 更加复杂的动画曲线:关键帧+ CAMediaTimingFunction分段,关键属性values、timingFunctions、keyTimes。
  3. 流程自动化:上个方法虽然可行,但是笨重而难以修改。动画流程的自动化需要用一个数学函数表示弹性动画。技术点:keyValue插值。

基于定时器的动画

摘要:在这一章中,我们了解了如何通过一个计时器创建一帧帧的实时动画,包括缓冲,物理模拟等等一系列动画技术,以及用户输入(通过加速计)。

性能调优

摘要:在这章中,我们学习了Core Animation是如何渲染,以及我们可能出现的瓶颈所在。你同样学习了如何使用Instruments来检测和修复性能问题。

代码应该运行的尽量快,而不是更快。也就是说业务代码不需要无止境的优化,当性能满足要求即可。

CPU/GPU

以下是CA是如何在这两个处理器之间分配工作的。

  1. 布局:准备视图/图层的层级关系,以及设置图层属性(位置、背景色、边框)的阶段。
  2. 显示:这是图层的寄宿图被绘制的阶段。
  3. 准备:CA准备发送动画数据到渲染服务的阶段,同时也是CA将要执行一些别的事务例如解码动画过程中将要显示图片的时间点。
  4. 提交:CA打包所有图层和动画属性,然后通过IPC(内部处理通信)发送到渲染服务进行显示。
    但是这些仅仅阶段仅仅发生在你的应用程序之内,在动画在屏幕上显示之前仍然有更多的工作。一旦打包的图层和动画到达渲染服务进程,他们会被反序列化来形成另一个叫做渲染树的图层树(在第一章“图层树”中提到过)。使用这个树状结构,渲染服务对动画的每一帧做出如下工作:
  5. 对所有的图层属性计算中间值,设置OpenGL几何形状(纹理化的三角形)来执行渲染。
  6. 在屏幕上渲染可见的三角形。
      所以一共有六个阶段;最后两个阶段在动画过程中不停地重复。前五个阶段都在软件层面处理(通过CPU),只有最后一个被GPU执行。而且,你真正只能控制前两个阶段:布局和显示。Core Animation框架在内部处理剩下的事务,你也控制不了它。

GPU相关的操作

宽泛的说,大多数CALayer的属性都是用GPU来绘制,但是有一些事情会降低(基于GPU)图层绘制,比如:

CPU相关的操作

大多数工作在Core Animation的CPU都发生在动画开始之前。这意味着它不会影响到帧率,所以很好,但是他会延迟动画开始的时间,让你的界面看起来会比较迟钝,以下CPU的操作都会延迟动画的开始时间:

IO相关工作

上下文中的IO(输入/输出)指的是例如闪存或者网络接口的硬件访问。

如何测试

确保在真实环境下测试你的程序

  1. 模拟器Mac上的GPU和iOS设备的完全不一样,模拟器不得已要在软件层面(CPU)模拟设备的GPU,这意味着GPU相关的操作在模拟器上运行的更慢,尤其是使用CAEAGLLayer来写一些OpenGL的代码时候。这就是说在模拟器上的测试出的性能会高度失真。
  2. 性能测试一定要用发布配置,而不是调试模式。因为当用发布环境打包的时候,编译器会引入一系列提高性能的优化,例如去掉调试符号或者移除并重新组织代码。
  3. 在你支持的设备中性能最差的设备上测试:如果基于iOS6开发,这意味着最好在iPhone 3GS或者iPad2上测试。如果可能的话,测试不同的设备和iOS版本,因为苹果在不同的iOS版本和设备中做了一些改变,这也可能影响到一些性能。例如iPad3明显要在动画渲染上比iPad2慢很多,因为渲染4倍多的像素点(为了支持视网膜显示)。

Instruments

将讨论如下几个工具:

高效绘图

摘要:本章我们主要围绕用Core Graphics软件绘制讨论了一些性能挑战,然后探索了一些改进方法:比如提高绘制性能或者减少需要绘制的数量。

软件绘图

代价高昂的绘图方式,绘制上下文需要的内存计算公式:WH4byte。

矢量图形

脏矩形

为了减少不必要的绘制,Mac OS和iOS设备将会把屏幕区分为需要重绘的区域和不需要重绘的区域。那些需要重绘的部分被称作『脏区域』。在实际应用中,鉴于非矩形区域边界裁剪和混合的复杂性,通常会区分出包含指定视图的矩形位置,而这个位置就是『脏矩形』。
调用-setNeedsDisplayInRect:来标记需要重绘的区域。

异步绘制

一些情况下,我们可以推测性地提前在另外一个线程上绘制内容,然后将由此绘出的图片直接设置为图层的内容。这实现起来可能不是很方便,但是在特定情况下是可行的。Core Animation提供了一些选择:CATiledLayer和drawsAsynchronously属性。

图像IO

摘要:在这章中,我们研究了和图片加载解压相关的性能问题,并延展了一系列解决方案。

加载和潜伏

在应用运行的时候周期性地加载和卸载图片。只要有可能,就应当设法在程序生命周期中不易察觉的时候加载图片。

缓存

文件格式——PNG/JPEG?

图层性能

摘要:本章学习了使用Core Animation图层可能遇到的性能瓶颈,并讨论了如何避免或减小压力。你学习了如何管理包含上千虚拟图层的场景。同时也学习了一些有用的技巧,选择性地选取光栅化或者绘制图层内容在合适的时候重新分配给CPU和GPU。

隐式绘制

通过以下三种方式创建隐式的寄宿图:1.使用特定的图层属性;2.特定的视图;3.特定的图层子类。

混合和过度绘制

为了加速处理进程,尽量不要使用透明图层,且将视图的backgroundColor属性设置一个固定的不透明的颜色,设置opaque属性为YES。

减少图层数量

对象回收:UITableView、CollectionView等。

CoreGraphics绘制

上一篇下一篇

猜你喜欢

热点阅读