[译] Core Animation 编程指南 - Core Animation 的基础

本文首发地址html

Core Animation 的基础

翻译说明
Layer - 图层
View  - 视图
复制代码

Core Animation 提供一个通用的系统来对你 App 的视图或者其余可视化元素作动画。Core Animation 并非替换你 App 的视图,Core Animation 是一种与视图集成的技术,用来给视图内容的动画制做提供更好的性能和支持。Core Animation 经过缓存视图内容转换为图形硬件能直接操做的位图来实现这一行为。在某些状况下,为了缓存视图内容,Core Animation 还定义了一种方法来指定任意可见内容,将该内容与你的视图集成,并将其与其余全部内容一块儿进行动画。git

你使用 Core Animation 来对你 App 的视图和可视对象的改变进行动画。大多数的改变是和你修改的可视化对象的属性相关联的。例如:你可能使用 Core Animation 去使视图的 position size 或 opacity 的改变进行动画。当你进行相似的改变时,Core Animation 会在该属性的当前值和你指定的新值之间作动画。一般,你不会像动画片同样,使用 Core Animation 每秒60次来替换视图的内容。实际上,你会使用 Core Animation 去移动屏幕上视图的内容,淡入淡出内容,对视图应用任意图形形变,或者改变视图的其余可视属性。github

图层 提供 Drawing 和 Animations 的基础

图层对象是由 3D 空间管理的 2D surface,它也是 Core Animation的灵魂。和视图相同的是,图层管理 surface 的几何信息,内容,和它可视化属性。和视图不一样的是,图层不定义它们本身的外观。图层 对象仅管理位图的状态信息。位图能够是视图绘制自身的结果,也能够是你指定的 image。为此,你在 App 中使用的 main layers 被认为是模型对象,由于它们主要是管理数据。这个概念很重要,由于它影响动画的行为。缓存

基于图层的绘制模型

你的 App 中大多数的图层不会作实际的绘制工做,图层对象会捕获你的 App 中提供的内容,而后将内容缓存为位图,有时也被称为 backing store。当你后面再修改图层的属性时,你所作的只是改变与图层对象相关联的状态信息。当改变触发一个动画时,Core Animation 会将图层的位图和状态信息传递给图形硬件,图形硬件使用新的信息来进行渲染,如图1-1。硬件操做位图进行动画要比软件快得多。 bash

图1-1 Core Animation 如何绘制内容

由于它操做的是静态的位图,因此基于图层的绘制与传统的基于视图的绘制技术有很大的不一样。基于视图的绘制,经过调用视图的 drawRect: 方法去使用新的参数去重绘内容来做为视图自己改变的结果。可是使用这种方法是很是耗性能的,由于他在主线程上使用 CPU 。Core Animation 经过硬件直接操做缓存的位图去实现一样的或者相似的效果,来避免性能上的消耗。app

虽然 Core Animation 尽量的使用缓存的内容,可是你的 APP 必须提供初始的内容而且不时的更新它。你的 App 有几种方法来提供图层对象的内容,详情请见提供图层内容ide

基于图层的动画

图层对象的数据和状态信息是与屏幕上图层的视觉显示分离的。这种分离赋予 Core Animation 一种方式去干预本身,而且对旧状态到新状态的改变进行动画。例如,改变图层的 position 属性 会致使 Core Animation 将图层从当前位置移动到新的指定位置。一样的,改变其余的属性也会致使恰当的改变。如图1-2。图层 属性触发动画机制的列表,可参见可动画的属性函数

图1-2 你能够在图层上执行的动画的例子

在一个动画执行的过程当中,Core Animation 会在硬件中完成全部的逐帧绘制。你所须要作的就是:给动画制定一个开始值和一个结束值,剩下的就能够交给 Core Animation 了。你也能够自定义你所须要的时间信息和动画参数,若是你不自定义,Core Animation 会提供合适的默认值。post

关于如何初始化动画和配置动画参数的更多信息,能够参见动画图层内容性能

图层对象定义它们本身的几何图形

图层的工做之一就是管理其内容的视觉几何(visual geometry)。视觉几何包含其内容的 bounds、在屏幕的 position 和图层是否被旋转、缩放、形变。和视图同样,图层也有 frame、bounds 属性用来定位图层的位置和内容。图层还有视图没有的属性,例如 锚点(anchor point):它定义了操做发生的点。 指定图层几何图形的某些方面的方式也与为视图指定信息的方式不一样。

图层使用两种类型的坐标系

图层利用基于点坐标系(point-based coordinate systems)和单位坐标系(unit coordinate systems)来指定内容的位置。使用哪个坐标系取决于传递信息的类型。当指定的值直接映射到屏幕坐标或必须指定相关联的另外一个图层的值时,使用基于点坐标系。例如图层的 position 属性。当值不该与屏幕坐标相关联,由于它与其余值相关联时,使用单位坐标系。例如:图层的 anchorPoint 属性指一个与图层自己的 bounds 相关联的点,该点是能够改变的。

基于点坐标系最多见的用法就是使用图层的 boundsposition 属性指定图层的 sizepositionbounds 定义了它自身的坐标系,并包含了它在屏幕上的 size。position 定义了图层在它父坐标系上的位置。虽然图层有 frame 的属性,但该值实际是由 boundsposition 属性计算出来的,而且图层不会常用 frame。

layer 的 boundsframe 属性的方向老是和底层平台的方向一致。下图展现了 iOS 和 OS X 系统的默认方向。在 iOS 中,默认的原点是图层的左上角,而在 OS X 系统上,默认是左下角。若是你想在两个系统上用一套 Core Animation 代码,你必须考虑到这些差别。

图1-3 iOS 和 OS X 默认的图层几何

在图1-3中,须要注意的是, position 属性是位于图层的中间。position 是基于图层的 anchorPoint 属性的值改变的几个属性之一。锚点表示坐标的起始点,更多详细信息请看 锚点影响几何操做 章节。

锚点是使用单位坐标系指定的几个属性之一。 Core Animation 使用单位坐标系表示当图层的尺寸发生改变时,值可能改变的属性。你能够将单位坐标系视为指定总可能值得百分比。单位坐标中每一个单位坐标的值的范围都是 0.0 到 1.0 。例如,在 x 轴,左边缘的坐标是 0.0 ,右边缘的坐标是 1.0 。在 y 轴,单位坐标值的方向改变取决于所在平台,如图1-4所示:

图1-4 iOS 和 OS X 上默认的单位坐标系

OS X 10.8 以前,当你须要的时候,可使用 geometryFlipped 属性去改变图层y 轴上的默认方向。当涉及到 filp 形变的时候,必须使用该属性去帮助图层获得正确的方向。例如:若是父视图使用 flip 形变,它的子视图的内容(以及与它们绑定的 layers)每每会倒置。在这种状况下,将子图层的 geometryFilpped 属性设置为 YES ,是一种简单有效的解决办法。在 OS X 10.8 之后,AppKit 将会自动处理该属性,不须要你再修改。对于 iOS 来讲,推荐你不要使用 geometryFlipped 属性。

全部的坐标值,不管是点仍是单位坐标值都是浮点数。使用浮点数能够容许你在正常的坐标值之间指定精确的位置。使用浮点数是很便捷的,尤为在输出或者绘制 Retina 显示器时,一个点是由多个像素点绘制的。浮点数使你能够忽略底层设备分辨率而专一于你所需精度的具体值。

锚点影响几何操做

layer 的几何操做的发生于图层的锚点相关联,你可使用 anchorPoint 属性来访问图层的锚点。当操做图层的 positiontransform 属性时,锚点的影响是很是显著地。position 属性老是和图层的锚点相关联的,你应用到图层上的任何形变效果也是和锚点相关联的。

图1-5 演示了锚点从默认值改变为一个不一样的值时,图层的 position 属性是如何变化的。即便图层没有在它的父边界中没有移动,将图层的锚点从中心移动到边界的原点也会改变 position 的值。

图1-5 锚点如何影响 position 属性

图1-6 展现了改变锚点的值是如何影响形变在图层上的应用。当你在图层上应用一个旋转的形变,旋转发生在锚点的周围。由于锚点默认是在图层的中间,这一般会建立一个你期待的旋转行为,若是你改变锚点,旋转的结果是不一样的。

图1-6 锚点是如何影响形变

Layers 能够在三维空间中操做

每一个图层有两个形变矩阵,你能够用这两个矩阵去操做图层和它的内容。CALayer 的 transform 指的是你想应用在它和它的 sublayers 上形变。在你想改变图层自己的时候使用该属性。例如,你可能想使用该属性去缩放、旋转或者暂时改变它的 position。sublayerTransform 属性只应用于 sublayers,它一般用于向场景内容添加透视效果。

经过将坐标值乘以数字矩阵来进行形变工做,以得到表示原始点形变版本的新坐标。由于 Core Animation 的值能够在三维空间中指定,每一个坐标点有四个值,坐标点必须和一个 4x4 矩阵相乘,如图1-7所示。在 Core Animation,图中的形变是经过 CATransformD 类型来表示的。幸运的是,你没必要去修改矩阵结构的字段来执行标准的形变。Core Animation 提供了丰富的函数去建立缩放、平移和旋转矩阵去作矩阵比较。为了使用函数来操做形变,Core Animation 延伸了键值编码支持,使你可使用键来修改形变。查看 CATransform3D 键路径 获悉你可修改的键。

图1-7 使用矩阵运算来转换坐标

图1-8 显示了一些常见形变的矩阵配置。任何坐标乘以 identity 矩阵返回坐标自己。对于其余形变,坐标的修改彻底取决于你改变的矩阵元素。例如,沿 x轴平移,你能够将形变矩阵的 tx 设为非零值,将 ty 和 tz 设为0。对于旋转,你能够提供目标旋转角度响应的正弦值和余弦值。

图1-8 常见的形变矩阵配置

图层树反映了动画状态的不一样方面

App 使用 Core Animation 有三组图层对象。每组的图层对象对将你的 App 的内容显示在屏幕上都有不一样的做用:

  • 模型图层树(图层树 - layer tree)中的对象是与你的 App 交互最多的。该树上的模型对象存储任何动画的目标值。每当你改变图层的属性时,都使用了其中一个对象。
  • 表示树(presentation tree)中的对象包含了任何正在执行的动画的当前值。 虽然图层树对象包含动画的目标值,但表示树中的对象会反映屏幕上显示的当前值。你永远不要修改该树中的对象。你可使用该树的对象来获取当前动画的值,也许你须要使用这些值来建立一个新的动画。
  • 渲染树(render tree)中的对象用来执行实际的动画,而且它是 Core Animation 的私有对象。

每组图层对象都被组织成一个分层结构,就像 App 中的视图。实际上, 对于为其全部视图启用图层的 App,每一个树的初始结构彻底匹配视图层次结构。可是,App 能够根据须要将其余图层对象(即与视图无关的图层)添加到图层层次结构中。你能够在这种状况下执行此操做,以针对不须要视图的全部开销的内容优化应用程序的性能。图1-9显示了在简单的iOS应用程序中找到的图层细分。示例中的 window 包含一个内容视图,该视图自己包含一个按钮视图和两个独立的图层对象。每一个视图都有一个对应的图层对象,它构成图层层次结构的一部分。

图1-9 与 window 关联的图层

图层树中的每一个对象,都在表示树和渲染树中有一个与之匹配的对象,如图1-10 所示。如上所述, App 主要使用图层树中的对象,但有时也会访问表示树中的对象。具体而言,访问图层树中的对象的 presentationLayer 属性来获取表示树中与之关联的对象。你可能须要访问对象来获取动画中间过程的属性的值。

图1-10 window 的图层树

你应该只在动画执行中的时候去访问表示树中的对象。当动画正在进行时,表示树包含当时在屏幕上显示的图层值。这个行为不一样于图层树,图层树老是反映你的代码设置的最后的值,而且等同于动画的最终状态。

图层和视图的关系

图层不能替代你 App 中的视图,即你不能仅基于图层来建立视觉页面。图层提供视图的基础结构。图层使绘制和动画视图的内容更加容易高效,而且保持高帧速率。然而,图层也有不少事情处理不了。图层不能处理事件、绘制内容、参与响应链,和其它不少事情。基于此,每一个 App 必须有一个或者多个视图来处理上述类型的交互。

在 iOS 中,每一个视图底层都由图层对象支持,可是在 OS X 你必须决定哪一个视图有图层。在 OS X v10.8 之后的版本,给全部的视图添加图层多是有意义的。然而,你不被要求必须这么作,你能够在不须要或者不想的地方使图层失效。图层会使你的内存开销增长,可是它们的优势远远超过这个缺点。在禁用图层支持以前,最好先测试 App 的性能。

当你的视图支持图层的时候,你建立了一个图层支持的视图(layer-backed view)。对于图层支持的视图,系统会在底层建立一个图层对象,而且保持图层和视图同步。 iOS 的全部视图和大部分的 OS X 视图是图层支持的视图。然而,在 OS X 中,你也能够建立图层托管视图(layer-hosting view),即你本身建立图层对象的视图。对于图层托管视图,AppKit采用了一种不干涉的方法来管理该层,而且不会根据视图的变化来修改它。

对于图层支持视图,不管什么时候,推荐你操做视图,而不是图层。在 iOS ,视图只是图层的一种封装,因此,你在图层上作的任何操做一般会正常工做。可是在 iOS 和 OS X 中都存在这样的状况:操纵图层而不是视图可能没法产生预期的结果。只要有可能,本文档指出了这些陷阱,并试图提供方法来帮助你解决这些问题。

除了与视图关联的图层以外,还能够建立没有相应视图的图层对象。你能够将这些独立的图层对象嵌入到 App 中的任何其余图层对象中,包括那些与视图相关联的图层对象。你一般使用独立的图层对象做为特定优化路径的一部分。例如,若是你想在多个地方使用相同的图像,你能够加载图像一次,并将其与多个独立的图层对象相关联,而后将这些对象添加到图层树中。而后,每一个图层引用源图像,而不是试图在内存中建立本身的图像副本。

有关如何为应用程序视图启用图层支持的信息,请参见在你的 App 中支持 Core Animation。有关如何建立图层对象层次结构的信息,以及什么时候建立图层对象层次结构的提示,请参见构建图层层次结构

最后

相关文章
相关标签/搜索