关于Core Animation
Core Animation是iOS与OS X平台上负责图形渲染与动画的基础设施。Core Animation能够动画视图和其余的可视元素。Core Animation为你完成了实现动画所需的大部分绘帧工做。你只需在配置少许的动画参数(如开始点位置和结束点位置)就可启动Core Animation。Core Animation将大部分实际的绘图任务交给了图形硬件处理,图形硬件会加速图形渲染的速度。这种自动化的图形加速让动画具备更高的帧率且更加平滑,但 这并不会增长CPU的负担而致使影响你应用的运行速度。
若是你正在开发一个iOS应用,你就已经使用到了Core Animation;若是你开发的是OS X应用,你仅需小小的付出就能够利用Core Animation的强大功能。以下图,Core Animation位于AppKit和UIKit的底层。它被紧密的集成到了Cocoa和Cocoa Touch视图工做流中。虽然被紧密的集成,Core Animation也存在扩展功能的接口,这些接口暴露给了应用的视图。使用这些接口能让你更细粒度地控制应用中的动画。
简介
你可能从不须要直接使用Core Animation,可是当你使用Core Animation,你应该了解Core Animation是你app基础设施中的一部分。
Core Animation管理着你的应用内容
Core Animation自身并非一个绘图系统。它 只是一个负责在硬件上合成和操纵应用内容的基础构件。Core Animation的核心是图层对象,图层对象用于管理和操控你的应用内容。图层将捕获的内容放到一副位图中,图形硬件可以很是容易的操控你的位图。在大 部分应用中,图层被做为一种管理视图内容的方式,可是你也能够建立标准的图层,这取决于你自身的须要。
更改图层属性会产生动画
你使用Core Animation建立的大部分动画都包含对图层属性的更改。像视图同样,图层对象也具备边框矩形、坐标原点、尺寸、不透明度、变换矩阵以及许多其余面向 可视的属性(如backgroundColor)。大部分这些属性的值发生了变化都将会触发隐式动画被建立。隐式动画是一种从旧属性值动画到新属性值的动 画形式。若是须要全面掌控动画行为,你能够考虑使用显式动画这些属性。
有组织的图层层级
有组织的图层之间存在着父子关系。图层的组织会影响到图层的可见内容。可见内容的管理与视图的管理方法类似。附到视图上的图层集合的层级镜像对应的视图层级。你能够将独立图层添加到图层的层级以扩充你的视图的可视内容。
使用动做对象改变图层的默认行为
经过动做对象能够作到隐式的图层动画。动做对象是 实现了一个预约义接口的常规对象。Core Animation使用动做对象实现与图层关联的常规的默认动画集合。你能够建立属于你本身的动做对象,以实现自定义的动画或者实现其余行为类型,而后你 将动做对象赋值给图层的某一属性。当属性发生变化,Core Animation检索你的动做对象并告诉动做对象执行对应的动做。
如何使用该文档
该文档为那些须要更全面的控制动画效果或打算利用图层提高绘图性能的开发者。该文档也介绍了iOS和OS X对图层和视图的合成。图层和视图的合成在iOS和OS X平台上是不一样的,理解这些不一样对于建立高效的动画相当重要。
预备知识
你应该了解你的目标平台的视图架构,以及熟悉如何建立基于视图的动画。若是你还未到该阶段,请阅读如下两篇文档:
对于OS X应用开发,你应该理解《
视图编程指南》中关于视图架构的描述。
Core Animation基础
Core Animation为动画视图和其余可视元素提供了一个通用的系统。Core Animation并非视图的替代品,相反,它是一种和视图相集成的技术。因为位图能够直接由图形硬件直接操控,经过将视图的内容缓存到位图中, 该技术可得到更优的性能且支持动画视图内容。除了缓存视图内容,Core Animation也定义了指定任意可视内容,而后将内容和视图集成,最后动画视图和其余可视元素的方式。
使用Core Animation让视图和可视对象的变化能以动画的形式呈现。大部分变化都与可视对象属性的更改相关。好比Core Animation能让视图的位置、尺寸或者透明度的变化以动画的形式呈现。当你更改了这些属性的值, Core Animation在当前属性值和最新指定的属性值之间进行动画。你通常不须要像卡通片那样,完成每秒60次的视图内容替换。相反,你应该利用Core Animation提供的移动视图、淡入淡出视图、对视图应用任意的变换、改变视图的其余可视属性的方式完成动画 。
图层是绘图与动画的基础
图层对象是组织在三维空间的二维平面。它是使用Core Animation执行任何操做的核心构件。和视图同样,图层的可管理信息包括几何结构、内容、可视属性;不一样于视图,
图层没有定义它本身的外观,图层仅管理周围位图的状态信息。位图能够是视图的绘图结果或者一张图片。所以主要的图层被认为是模型对象,由于它们主要是用于管理数据。此概念务必记住,由于它影响到动画的行为。
基于图层的绘图模型
大部分图层不作实际的绘图操做。相反,图层捕获应用的内容并缓存它们到位图中。位图有时也被称为储备(backing store)。当你随后改变了一个图层的属性值,你作的全部只是改变了与图层对象相关联的状态信息。当你的更改触发了一个动画,Core Animation传递图层的位图和图层的状态给图形处理硬件。图形处理器所作的工做是使用得到的信息渲染位图,如图1-1所示,用图形处理硬件操纵位图 要比图形处理软件能得到更高的动画效果。
由于操纵的是静态的位图,基于图层的绘图和基于视图的绘图在技术上有明显的不一样。对基于视图的绘图,对视图的改变常常会触发调用视图的 drawRect:方法以重绘视图内容。可是此种方式的代价相对较高,由于它是CPU在主线程上的操做。Core Animation经过尽量的使用图形硬件操纵缓存后的位图来避免了这种开销,从而完成相同或类似的效果。
虽然Core Animation尽量的使用缓存后的内容,但也必须提供初始内容并不时地更新它。
基于图层的动画
图层的数据和状态信息是从图层内容的可视呈现中被分离了出来的。这种分离性给了Core Animation介入以及从旧的属性值动画到新的属性值的机会。例如改变一个图层的position属性会引发Core Animation将图层从当前的位置移动到新的具体位置。对其余属性作类似的改变将引发适当的动画效果。图1-2展现了一些能够执行在图层上的动画类 型。
图1-2 可在图层上执行的动画类型
在动画运行期间,Core Animation使用硬件帮你完成每一帧的绘制工做。你只须要指定动画的开始点和结束点,剩下的交由Core Animation完成。如若须要,你也能够指定自定义时间信息和动画参数,若是你没有指定, Core Animation会提供适当的默认值。
图层对象定义了本身的几何结构
图层的其中一项任务就是管理自身内容的可视几何。可视几何包含关于图层内容边界、在屏幕上的位置,是否图层已被旋转、缩放,或应用了某种变换。 与视图相似,一个图层有一个frame和bound属性,你可使用这两个属性来定位图层和它的内容。图层也有一些视图所没有的属性,好比anchor属 性,任何变换操做都是围绕该点运转的(能够理解为一个按在图层上的图钉)。图层的某些几何概念的指定方式与视图信息的指定方式也有不一样。
图层使用两种类型的坐标系统
图层利用基于点的坐标系统和单位坐标系统指定内容的布局。坐标系统的选择依赖于被传达的信息类型。当指定的值是直接映射到屏幕或相对于其余图层 的坐标,好比图层的position属性,则使用基于点的坐标系统。当指定的值是相对于一些其余的值,与屏幕坐标不相关联,则使用单位坐标。好比图层的 anchorPoint属性,anchorPoint属性指定了相对于图层边界的一个点。anchorPoint属性能够更改。
基于点的坐标最经常使用于指定图层的尺寸和位置。可经过图层的bounds和postion属性设定图层的尺寸和位置。bound定义了图层自身的 坐标系统并包含图层在屏幕上的尺寸。position属性定义了图层相对于父坐标系统的位置。虽然图层有一个frame属性,该属性其实是从 bounds和position属性派生而来,极少被使用。
图层的bounds和frame矩形的方向始终与底层平台的默认方向相匹配。图1-3显示了iOS和OS X平台上边界矩形的默认方向。在iOS中,默认状况下边界矩形的原点在图层的左上角。而OS X上边界矩形的原点则在左下角。若是你在iOS和OS X版本的app之间共享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坐标的方向。当翻转变换被调用时,使用该属性来调整图层的方向有的时候是 必需的。若是父视图使用了翻转变换,它的子视图内容(以及它对应的图层)将常常被颠倒。在这种状况下,设置子图层的geometryFlipped属性为 YES是一种修正该问题最简单的方法。在OS X 10.8及以上版本,AppKit负责管理该属性,你不该该更改它。对于iOS app,不推荐使用geometryFlipped属性。
全部的坐标值,不管是点仍是单位坐标都以浮点数指定。使用浮点数容许你更精确的指定可能落在整数坐标值之间的点。特别是打印或向retina屏幕绘图,浮点值都会很方便。浮点值容许你忽略底层设备的分辨率,而你只须要指定值的精度。
锚点影响几何结构的操做
图层的几何操是相对于图层的锚点进行的,anchorPoint属性能够访问图层的锚点值。当改变图层的postion和transform属性值,锚点的影响就很明显。position属性是相对于图层的锚点被指定。而且任何你对图层阴影的变换操做也是相对于锚点。
图1-5说明了改变锚点对图层position属性的影响。尽管图层没有在它的父边界内移动,将锚点从中心点移动到图层边界的原点将改变position属性值。
图1-5 锚点是如何影响图层的position属性
图1-6显示了锚点的变化是如何影响到应用在图层上的变换。当你对图层应用了一个旋转变换,图层将围绕中心点旋转。由于默认状况下,锚点被设定在图层的中心位置。通常建立这类旋转行为正是你所指望的。然而若是你改变了锚点值,旋转的结果也会发生变化。
图1-6 锚点是如何影响图层的变换
图层可在三维空间中操做
图层有两个操控图层和内容的变换矩阵,transform和sublayerTransform属性。CALayer的transform属性 用来指定应用到图层和它内嵌的子层上的变换。一般当你想更改图层自己则使用该属性。比方说,你可能使用该属性缩放或旋转图层,或是临时的改变图层的位置。 sublayerTransform属性定义了仅应用在子层上的变换以及给场景内容添加透视效果。
变换行为由多个坐标肯定,这些坐标经过一个数字矩阵来获取,获取的坐标结果是原始点被变换后的版本。由于Core Animation的值可在三维空间中指定,每一个坐标点有四个值,这四个值须要和一个4*4的矩阵相乘。
如图1-7所示。在Core Animation中,图中的变换由CATransform3D类型表示。幸运的是,你不须要直接更改这个结构中的域值来执行标准变换。Core Animation为建立缩放、平移、旋转矩阵以及矩阵比较提供了综合的函数集。除了使用函数操纵变换。Core Animation扩展了键值编码以支持你使用键路径更改一个变换操做。
图1-7 使用矩阵数学转换一个坐标
图1-8显示了对一些常见的变换矩的配置。任何坐标与单位矩阵相乘将返回彻底相同的坐标。坐标如何被更改彻底依赖于你变化的矩阵因子。好比,为 了仅在X轴上平移,你只需对变换矩阵的tx因子应用一个非零值,并让ty和tz值为0。若是是旋转,应用一个旋转角度的正弦和余弦值。
图1-8 常见变换的矩阵配置
不一样的图层树反映了不一样的动画状态
使用Core Animation的app拥有三个图层对象集合。每个图层对象集合在呈现app内容上都扮演着不一样的角色。
Ø模型图层树中的对象(或简称“图层树”)用的最多。在这个树中的对象是模型对象,模型对象负责存储全部动画的目标值。不管什么时候改变图层的属性值,你使用的始终是某一个模型对象。
Ø呈现树中的对象包含全部运行中的动画的瞬时值。图层树对象包含的是动画的目标值,而呈现树中的对象表明显示在屏幕上动画的当前值。你不该该更改这个树中的对象。相反,你使用这些对象来读取当前动画的值,可能用于建立开始于这些值的新的动画。
Ø在渲染树中的对象执行实际的动画,而且对Core Animation是不公开的。
每个图层对象集合被组织在一个层次结构中,相似于app中的视图。事实上,在一个全部视图都支持图层功能的app来讲,每个树的初始结构完 全与图层的层次相匹配。一个app能够添加另外的图层对象,所以图层与视图是不相关联的。能够按照需求将图层对象插入到指定的视图层级中。你可能为了优化 app内容的性能而选择加入图层对象而非视图,缘由在于图层的开销要比视图低。图1-9展现了出如今一个简单iOS app的图层分解图。在示例中窗口包含了一个内容视图,内容视图包含了一个按钮视图和两个独立的图层对象。每个视图拥有一个相对应的构成图层层次的图层 对象。
图1-9 与窗口相关联的图层
在图层树中的每个对象,在渲染树和呈现树中也存在一个与之匹配的对象。如图1-10所示。正如以前提到过的,app主要与图层树中的对象进行 交互,但可能有时会访问呈现树中的对象。具体地,访问图层树中对象的presentationLayer属性将返回一个在呈现树中相对应的对象。你可能会 经过该对象获取在动画执行过程当中的某一时刻的属性值。
图1-10 窗口中的图层树
重要:只在动画运行时访问呈现树中的对象。当动画在进行中,呈现树就包含了图层显示在屏幕上的那一刻的值。该行为与图层树不一样,图层树永远只表示最终的目标值。
图层不是视图的替代品。所以没法建立一个基于单一图层对象的可视界面。图层是视图的基础设施。具体地,图层让视图的绘图和动画更简单和高效,并 且能在绘图和动画时保持高帧率。然而许多事情图层没法作到。图层不能处理事件、绘制内容,特别是在响应链中,或是作一些其余的事情。所以,每一个app必须 有一个或多个视图来处理这类交互。
在iOS中,每个视图有一个相对应的图层对象。但在OS X中,你必须决定哪个视图拥有图层。OS X 10.8以及以前的版本中,添加图层到全部视图上也许是有意义的。然而你没必要这样作,你仍能够关闭图层防止没必要要以及无根据的开销。
图层在某种程度上减小了程序的内存开销,图层的这些优势远远超出它的缺点。因此最好是在禁用图层支持以前测试你app的性能。
当你的视图支持图层后,此时该视图被称为layer-backed视图。对于layer-backed视图,系统负责建立底层的图层对象,并保 持与视图的同步。因此iOS视图都是支持图层的而且在OS X中的大部分视图也是如此。可是在OS X中,你也能够建立图层托管(layer-hosting view)视图,该视图的图层对象由你来提供。
注意:对于layer-backed视图,建议只 操做视图而不是图层。iOS中视图仅仅是对图层对象的精简包装,因此任何你对图层的操做一般都会正常工做。可是iOS和OS X平台上操纵图层而不是图层可能不会取得预期的结果。该文档会尽量的指出这些陷阱并提供一种方式让你能够与它们工做。
除了与视图相关的图层,你也能够建立独立的图层对象。你能够嵌入这些独立图层对象到任何其余图层对象中,包括与视图相关的图层。你通常使用图层 对象做为具体优化方法的一部分。好比说,若是你想使用相同的图片在多个地方,你能够只加载图片一次,而后将图片和多个独立的图层对象相关联,最后添加这些 图层对象到图层树中。每个图层只会引用源图片而不是尝试在内存中建立自身对图片的拷贝。