Core Animation 为你的 app 提供视图和其余视觉元素的通常动画建立。Core Animation 并非替代你 app 的视图,它是一种集成在视图中为视图内容提供更好性能和支持的动画技术。它经过缓存视图内容到位图实现,能够直接地被图形硬件操做。有时这种缓存行为须要你屡次考虑怎么呈现和管理你 app 的内容,可是多数时候你使用 Core Animation 并不须要知道这种缓存技术。除了缓存视图内容,Core Animation也定义一种方式来明确任意的视图内容,并集成此内容到你的视图中和其余的一块儿表现动画。html
你用 Core Animation 把 app 视图和可视对象的变化用动画的形式表现出来,大多数都是经过修改视图的属性,好比,你可能使用 Core Animation 更新视图的position,size或者 opacity。Core Animation 根据你指定的属性值和现有值的不一样造成动画。你不须要想卡通动画那样每秒60次的替换视图内容,只须要在屏幕中移动视图、淡入淡出视图内容,应用任意的图形形态到视图,或者改变视图的可视属性。ios
Layer 对象 是在3D空间中组织成的2D界面,是Core Animation 的核心。像视图同样,layer 管理着几何、内容和界面的可视属性之类的信息。不一样于视图的地方是它并不定义本身的形态。一个 Layer 仅仅管理围绕着位图的状态信息。位图自己既能够是视图的最终绘制形态,也能够是一张你指定的图片。所以,你在 app 中使用的核心 layer 主要管理的是数据,能够当作数据模型。这一点须要谨记,它会影响到动画的效果。缓存
在你的 app 中,大部分的 layer 并不作实际的绘制,只捕捉 app 提供的内容并缓存它们到位图中,此位图有时被做为 backing store 。缓存到位图以后修改 layer 的属性,实际修改的都是 layer 对象相关的状态信息。当 layer 的属性值变动触发动画时,Core Animation 传递 layer 的位图和状态信息给图形卡,图形卡根据状态信息渲染位图,如图 1-1 。用硬件渲染位图比在软件中快不少。性能优化
图 1-1 How Core Animation draws content
app
因为是直接操做静态的位图,layer-based 的绘制技术彻底不一样于 view-based 的绘制技术。view-based 绘制,是视图改变后调用自身的方法 drawRect: 根据新的参数重绘,这种方式会下降性能,由于重绘的动做是经过 CPU 计算后在主线程上完成的。Core Animation 经过图形卡操做缓存的位图分担了CPU的负担来完成形似或相同的效果。框架
尽管 Core Animation 尽量的使用缓存内容,你的 app 仍是得提供内容的初始化和一次次的更新。Providing a Layer's Contents 这一章节中会详细地描述怎么为你的 app 提供 layer 内容对象。ide
layer 对象的数据和状态信息从屏幕的内容呈现中解耦出来。这种解耦为 Core Animation 提供了一种方式插入到自身,并以动画的形式展示状态值的变动。例如,修改 layer 的position 属性会致使 Core Animation 把 layer 从当前位置移动到新的位置。其余属性的修改也会产生相似的动画。图 1-2 展现了几种你能够在 layer 中表现的动画类型。在 Animatable Properties中列出了能够触发动画的 layer 属性。性能
Figure 1-2 Examples of animations you can perform on layers
测试
在一次动画期间,Core Animation 在硬件上为你绘制了全部的图形框架。你所须要作的只是明确动画的起始点。一样地你也能够能够根据须要自定义动画的参数和时间,若是你没有自定义这些参数和时间,Core Animation 会提供合适的缺省值。优化
怎么初始化、配置动画参数的信息,详见 Animating Layer Content。
layer的其中一项工做就是根据其内容管理视觉几何图形。可视几何图形包括各类信息,诸如内容的 bounds、在屏幕上的 position,以及layer是否已经发生旋转、缩放、变形。像视图同样,layer 也有能够用来定位和展示内容的 frame、bounds。layer 也有一些视图不具备的属性,像定义操做发生点的 anchor point。一些列举 layer 几何图形的方面是明显不一样于视图的。
layer 利用 point-based coordinate systmes(基于点的坐标系统)和unit coordinate systems(单元坐标系统)明确内容的放置。坐标系统的使用依据被传递的信息类型。Point-based 坐标在有明确的屏幕坐标值或被明确地关联到另个一 layer 时使用,例如 layer 的 position 属性。Unit 坐标在属性值和屏幕坐标无关联但和其余有关联时使用,例如,layer 的 anchorPoint 坐标,它指出了一个和 layer 自身的bounds关联且能够修改的点。
point-based 坐标大多数时候经过 layer 的 bounds 和 position 属性明确 layer 的 size 和 position。bounds 定义了 layer 的坐标系统,包含 layer 在屏幕上的尺寸。position 属性定义了layer相对于父层坐标系统的定位。尽管 layer 有 frame 属性,其实 frame 源于 bounds 和 position 两个属性,使用的频次不高。
layer 的 bounds 和 frame 方向和平台的默认方向相匹配。图 1-3 展现了bounds 和 frame 在 ios 和 os x上的默认方向。ios中,bounds的原点方向默认在 layer 左上角,而 os x 中默认在左下角。若是你在 ios 和 os x 之间共享 Core Animation 的相关代码,须要注意两个平台的这点差别。
Figure 1- 3 The default layer geometries for iOS and OS X
在图 1-3 中须要注意一点,position
属性被定位在 layer 的正中间,这个属性值的明显变化是众多基于 layer 的 anchorPoint 属性值之一。锚点表明肯定的坐标原点的点,在 Achor Points Affect Geometric Manipulations 中有详细的概述。
锚点是众多使用 unit 坐标系统来肯定属性值的属性之一。在 layer 的 size 属性改变时会影响一些属性的改变,unit 坐标系统在Core Animation 中就是用来表明这些属性的。你能够认为 unit 坐标就是可能值的具体百分比。在 unit 坐标控件中每个坐标的范围是 0.0~1.0 。例如,在 x 轴方向上,左边距的坐标是 0.0,右边距则是 1.0 。在 y 轴方向上,unit 坐标值的变化取决于平台,若是 1-4 所示。
Figure 1-4 The default unit coordinate system for iOS and OS X
注意:在 OS X 10.8以前,geometryFlipped 属性能够在须要的时候修改 y 轴的默认方向。当 layer 包含翻转变化时layer就须要这个属性来修改方向。例如,若是父视图使用了翻转变形,它的子视图(他们相关的layer)将经常被倒置,在这时 设置子视图们的 geometryFlipped 属性为 YES 将是组简单的解决方式。OS X 10.8 和以后的系统中,AppKit 为你管理这个属性。对于 iOS 应用,最好不要使用这个属性。
全部的坐标值,不管是坐标点仍是 unit 坐标都是浮点数。浮点数的使用能够指出可能介于正常的坐标值之间位置的精确值,并且还很方便,尤为是打印时或者绘制一个点表明多个像素的 Retina 显示时。浮点数的使用可让你忽略对设备展现的依赖,仅仅须要指出你想要的精度值便可。
你能够用 layer 的 achorPoint 属性来操控 layer 的集合形状。最值得注意的是锚点的改变会影响到 position 或 transform 属性的操做。position 属性老是依赖于layer 的锚点来明确,而任何你应用的变形也取决于相关的锚点。
图 1-5 说明了锚点从默认值改变为另外一值时对 layer 的position 属性的影响,尽管 layer 没有在父层的 bounds 中并无移动,从 layer 的中心移动锚点纸 layer 的 bounds 原点改变了 position 属性值。
图 1-5 How the anchor point affects the layer's position property
图 1-6 展现了原点的变化怎样影响应用在 layer 上的变形。当你在 layer 上应用旋转变形时,旋转是以锚点为中心。由于锚点默认被设置在 layer 的中间,此时能够产生你所指望的旋转形态,然而更改了毛点后,旋转的结果就不一样了。
图 1-6 How the anchor point affects layer transformations
每个 layer 都有两个 transform 矩阵,你能够用来操控 layer 和它的内容。CALayer 的 transform 属性指出了你想应用在 layer 和它内嵌的子 layer形态。通常在你想修改 layer 自身时用这个属性。例如,你能够用此属性等比例缩放或旋转 layer 或 改变 暂时性地改变 position。sublayerTransform 属性定义了额外的变形,仅仅用在子 layer 中,经常用来往图形内容中单独添加可见视觉现象。
Transform 依靠数值矩阵的多个坐标值得到新的坐标集,此作标记表明原点变形后的版本。Core Animation 的值能够在三维中指出,因此每一个坐标点有四个值,能够用 4x4的矩阵标示,如图 1-7 。图形中的 transform 对应 CATransform3D 类型。幸运的是你不用直接修改这个结构的字段来造成一个变形,Core Animation提供综合的方法集来建立 scale, translation和 rotation 矩阵,并且能够作矩阵比较。另外关于方法操做变形,Core Animation 用键值对的编码,支持直接用键值改变变形。你能够修改的键列表,详见 CATransform3D Key Paths。
图 1-7 Converting a coordinate using matrix math
图 1-8 显示了通常变形中你会用到的矩阵配置。身份坐标值和其余坐标值的乘积返回的仍是一样的坐标。其余的变形中坐标怎么被修改彻底依赖矩阵元素的改变。例如,沿着X轴移动,你只须要为矩阵中的 tx 元素提供一个非零的数值,把 ty 和 tz 的值设为 0 便可。再好比旋转,你提供旋转角度的正弦、余弦值就好了。
图 1-8 Matrix configurations for common transformations
你能够建立和操做变形的相关方法,详见 Core Animation Function Reference
一个 app 在使用 Core Animation 时有三个 layer 对象集。当 app 的内容在屏幕显示时每一 layer 对象集都扮演着不一样的角色:
每个 layer 对象集在 app 中都是像视图同样以层次结构组织起来的。事实上在 app 的全部视图中,有效的 layer 在初始时是何视图的层次机构相匹配的。app 能够根据需求添加额外的 layer 对象到已有的 layer 层次中(layer 和 view 是不相关的),当对一个视图的最顶层不须要的内容就行性能优化时你可能会用到。图 1-9 展现了 layer 在一个简单 ios app 中的分解。示例中的 window 包含内容视图,内容视图包含一个 button 视图和两个单独的 layer 对象,每个视图都有相关的 layer 对象,它们一块儿构成了 layer 的层次。
图 1-9 Layers associated with a window
如图 1-10,对于每个 layer 树的对象,presentation 和 render 树对象是一一对应的。正如以前提到的,app 主要用 layer 树中的对象工做,有时会访问 presentation 树的对象。使用 layer 树的对象 presentationLayer 能够得到 presentation 树相关的对象。当动画进行时你可能会想得到属性的相关值,访问这个对象便可。
图 1-10 The layer trees for a window
重要提示:你只能在动画进行时访问 presentation 树的对象。在动画的进行过程当中,presentation 树包含 layer 显示在屏幕上那一瞬间的各类值。这种行为和 layer 树相比是彻底不一样的,layer 树老是反应你代码的最终值,也就是动画最终的状态。
layer 并非你 app 中视图的替代,你不能在一个单独的 layer 对象上构建一个可视界面。Layer 能够为你的视图提供基础设施。最明确的一点就是 layer 能够提升视图内容的绘制和动画的效率和框架率。可是还有一些其它的 layer 完不成,不能处理事件,绘制内容,成为响应链的一环,或者其它的一些事情。所以每个 app 必需要有一个或多个视图来处理这类的交互。
在 iOS 中,每个视图都是构建在一个相关的 layer 对象之上,在 OS X 中须要你手动决定哪一个视图应该有 layer。在 OS X v10.8 及以后的版本中,为全部视图添加 layer 是比较合情理的,可是这也不是必须的,你仍然能够为那些不合理的视图内容禁用 layer。Layer 的使用确实会增长 app 的内存使用,可是它的使用利大于弊,因此在禁用 layer 时最好测试一下 app 的性能。
当你开启 layer 对一个视图的支持时,此视图就被做为一个 layer-backed 视图。在 layer-backed 视图中,系统负责建立视图之下的 layer,保持视图和 layer 之间的同步。全部的 iOS 视图都是 layer-backed 视图,OS X 大部分视图是。可是在 OS X 中你能够建立一个 layer-hosting 视图,一个你为其提供 layer 对象的视图。关于 layer-hosting 视图,AppKit 提供了 layer 方便的管理方式,不用在视图的响应变换时修改它。
注意:对于 layer-backed 视图,强烈建议你尽量的管理视图而不是它的 layer。在 iOS 中,视图仅仅是对 layer object的封装,所以你对 layer 的操做通常都会正常运行。可是不管是 ios 仍是 os x,都出现过用修改 layer 代替视图修改时发生错误的情况。本文档会尽量的指出这些误区。
尽管 layer 和视图有关联,你仍然能够建立一个和视图不相关的 layer 对象。你能够把这个单独的 layer 对象嵌入到其余的 layer 对象中,而后把他们和一个视图相关联。在性能优化时通常会采用此方法。例如,若是你想在多个地方使用同一张图片,你能够只加载一次这张图片,把它和几个单独的 layer 对象相关联,而后把他们加入到 layer 树中,那么每一个 layer 都会引用它,而不是从新 copy 到内存中。
怎么在 app 中为视图启用 layer,详见 Enabling Core Animation Support in Your App。关于怎么建立 layer 对象层和其余的提示,详见 Building a Layer Hierarchy。