Core Animation 文档翻译 (第二篇)—核心动画基础要素

 


 

前言html

 

核心动画为咱们APP内Views动画和其余可视化元素动画提供了综合性的实现体系。核心动画不是咱们APP内Views的替代品,相反,它是一种结合Views来提供更好性能和支持Content动画的技术。它经过将Views的Content缓存进能够被绘图软件直接操做处理的Bitmaps来达到这种高性能。在某些状况下,这种缓存技术可能须要咱们从新思考咱们将要如何呈现和管理咱们的APP的Content,可是大多数状况咱们能够在不去考虑这种缓存带来的影响而直接使用核心动画。除了缓存View 的Content以外,核心动画也定义了一种制定任意可视化Content,使咱们的Views与可视化Content结合起来,并使该可视化Content和其余事物一块儿动画。编程

 咱们使用核心动画让咱们APP内Views和可视化对象特性的变动以动画的形式过渡。许多可视化对象的变动和修改可视化对象的属性有关联,例如,咱们可能使用核心动画来为View的position、size、opacity的改变制做动画。当咱们调整了相似的属性,核心动画将会制做在当前属性值和咱们指定的新值之间过渡的动画。咱们尤为不该该使用核心动画以60次每秒的频率替换View的Content,例如不该该使用核心动画以这种方式制做卡通片。相反,咱们使用核心动画从屏幕上移除View的Content,渐隐渐出Content,任意调整Views的图形transformation,或者改变View的其余可视化属性。缓存

 

Layers 提供绘画和动画的主要部分app

 

Layer 对象是2D平面,并被组织到3D空间;核心动画能作的全部事情的核心也是Layer。和Views同样,Layers管理他们各自的几何、Content和其余可视化属性。和Views不同的是,Layers没有定义显示表面。一个Layer仅仅管理一个bitmap相关的状态信息;这个bitmap他自己多是一个View的绘制结果或者咱们制定的固定的图片,由于Layers主要管理data,所以APP中咱们使用的大部分Layers被视为模型对象。这个概念很重要,须要记住,由于它影响动画的行为ide

 

基于 Layer的绘制模型函数

 

APP中许多Layers没有作任何实际绘制。相反,一个Layer捕获咱们APP提供的Content并将他们缓存进一个bitmap中,这个bitmap有时候被称做辅助存储。当咱们接着改变Layer的属性,全部咱们作的即是改变Layer对象相关联的状态信息。当一个改变出发一个动画,核心动画将Layer的bitmap和状态信息传递给绘图硬件,绘图硬件使用这些新的信息渲染bitmap,Figure 1-1图显示的流程。在硬件中操做处理bitmap将会产生更快的动画,相较于使用软件。性能

                                                                     

 Figure 1-1  How Core Animation draws content测试

由于他操做处理一个静态bitmap,基于Layer的绘制明显不一样于传统的基于View的绘制技术。在基于View的绘制中,View的变化一般会调用该View的drawRect:方法 来使用新的参数绘制Content;可是这种方式的绘制的消耗是很高的,由于他是使用CPU在主线程上完成的。核心动画经过一种流程避免这种高昂的消耗--当可以经过操做处理硬件内缓存的bitmap达到相同或类似的效应时候。优化

尽管核心动画尽量的使用缓存的Content,咱们的APP仍旧提供这个初始化的Content和不时的更新Content。APP中有几个方法为经过Content提供Layer对象,在Providing a Layer’s Contents(后续有翻译)中有详细描述。动画

 

 基于Layer的动画

 

Layer对象的数据和状态信息与屏幕上Layer的Content的可视化展示之间是解耦的。这种解耦使得核心动画处于Layer对象与屏幕上可视化的展示之间,并可以使这个从旧状态值到新状态值的过渡显示为动画。例如,改变一个Layer的position属性会引发Layer从它当前position移动到新指定的position。其余属性的类似变动也会引发相应的动画。Figure 1-2展示了几个咱们可以在Layers上执行的动画种类。Layer能够触发动画的属性,能够参见Animatable Properties。(后续会有翻译)

                                                             

  Figure 1-2  Examples of animations you can perform on layers

 

在动画的过程期间,核心动画在硬件中作了全部的逐帧绘制。全部咱们应该作的仅仅是制定动画的开始和结束点,并开启核心动画,核心动画将会作剩下的工做。咱们也能制定自定义的必要的timing信息和动画参数;然而,若是咱们没有设定相应的默认值,核心动画将会提供适当的默认值。

更多信息关于如何去开启动画和配置动画参数参见Animating Layer Content。(后续会有翻译)

 

Layer 对象定义他们的几何形状

 

Layer的功能之一就为Layer自身的Content管理可视化几何形状。可视化几何形状所包含的信息:Content在屏幕上的bounds和position和该Layer是否经过任何途径被旋转、缩放、transformed。就像一个View,一个Layer也有frame和bounds属性以用于调整该Layer和Content的位置。Layers也有其余和View也有的属性,例如anchor point(锚点),能够围绕锚点制做动画的点。咱们指定一些Layer的几何方面值与指定View相应的值是有区别的。

 

Layers 使用两种坐标系统

 

Layers 利用基于点的坐标系统和单元坐标系统指定Content的位置。具体使用哪一种坐标系统取决于被传递的信息类型。当指定映射到屏幕坐标值和被关联到另外的Layer时候,这两种状况将会使用基于点的坐标,例如Layer的position 属性。当某些值不该该被绑定到屏幕坐标系统时候(由于它是关联一些其余值的)会使用到单元坐标系统。例如,Layer的anchorPoint属性是指定和Layer自己的bounds相关联的点,bounds会变,就会影响单元坐标系统内anchorPoint。

基于点坐标系统最广泛的用途就是指定Layer的size 和position,其实就是指咱们使用Layer的bounds和position属性。bounds 定义Layer自己内部坐标系统并包含Layer在屏幕上的size。position属性定义了Layer在它父坐标系统上的位置。尽管Layers有frame属性,frame属性其实是从bounds和position属性获得的,Layer的frame不经常使用。

Layer的bounds和frame的方向老是和所在的平台默认方向匹配的。Figure 1-3展现了iOS和OS X两个平台的默认方向。在iOS里面,原点的位置默认是左上角,在OS X平台默认是左下角。若是咱们在两个平台之间分享核心动画的代码,咱们必须考虑二者的不一样之处。

                                                       

  Figure 1-3  The default layer geometries for iOS and OS X

在图1-3中有件事情须要注意:position属性是Layer的中心点。有几个属性的值是基于Layer的anchorPoint属性,position就是其中之一。anchor point 表明了特定坐标系统的起点,锚点被描述的更详细在文档Anchor Points Affect Geometric Manipulations。(后续会有翻译)

有几个属性的值是咱们使用单元坐标系统指定的,anchor point 就是其中之一。核心动画使用单元坐标系统表明属性值,这些属性值可能会发生变化当Layer的size改变的时候。咱们能够把单元坐标视为一个总体值的百分比(例如宽度被设定为为100,锚点是50%)。在单元坐标内,每一个坐标值的变化范围是0.0到1.0。例如沿着X轴,左边缘是0.0,右边缘是1.0。沿着Y轴单元坐标的值的变化和所在平台有关,如图1-4所展现。

   

  Figure 1-4  The default unit coordinate systems for iOS and OS X

 

 

 注意:直到OS X 10.8,当有须要时,geometryFlipped属性可以调整一个Layer的Y轴方向。当涉及到反转transforms调整时,经过使用这个属性来矫正Layer的方向是颇有必要的。例如若是父View使用一个反转transform调整时,子Views的contents(和他们相应的Layers)将会被反转。在这些状况下,设置子Layers的geometryFlipped属性为YES是可以改正问题的一个简单的方式。在OS X 10.8和以后,AppKit 管理这些属性而且咱们不该该修改他。对于iOS APPs,彻底不建议使用geometryFlipped属性。

全部的坐标值,不管点坐标仍是单元坐标,它们都是浮点型数值,使用浮点型使咱们可以指定精细的位置,这些位置可能在标准坐标值之间。浮点值的使用很便利,尤为在印刷或者当会知道Retina屏幕时候,Retina屏幕的一个点可能表明多个像素。浮点值容许咱们忽略基于设备的分辨率,可直接调整到某个咱们想要的精确值。

 

Anchor Point 影响几何图形操做处理

 

Layer的几何相关操做都受到Layer的anchor point的影响,即Layer的anchorPoint属性。当调整position或transform属性的时候,anchor point的影响会很明显。position 属性老是和Layer的anchor point关联在一块儿的;对Layer作的transformations调整也老是和anchor point 关联着的。

图1-5所描述了——Layer的anchor point 从默认值到一个新值的调整是如何影响position属性的。anchor point从Layer的中心点移动到Layer的origin,改变了Layer的position属性,可是Layer在他父Layer的bounds内坐标没有发生变化。

  Figure 1-5  How the anchor point affects the layer’s position property

 

 

图1-6展示了anchor point的改变是如何影响Layer的transforms变换的。当咱们对Layer作旋转transform调整时候,旋转将会绕着anchor point发生。因为anchor point默认在Layer的中心位置,正常的旋转调整将会是围绕Layer的中心发生;若是咱们改变anchor point,旋转的结果将会发生变化。

 Figure 1-6  How the anchor point affects layer transformations 

 

 

Layer 的三维空间操做

 

每个Layer有两个transform 矩阵,咱们可使用这两个矩阵来操做处理Layer的contents。Layer的transform属性指定的变换将会被应用到Layer自己和内嵌的sublayers。一般咱们想使用这个属性来调整Layer自己,例如,咱们可能使用transform属性来缩放或旋转某个Layer,或者临时调整Layer的position。sublayerTransform属性定义的变换仅仅用来调整Layer的sublayers,在某些场景中它也一般备用来添加人眼视角效应。

Transforms 经过矩阵变换改变当前坐标值获得新的坐标值(coordinate),新的坐标值表明着转换后的坐标值。因为核心动画能够指定三维空间变换,在矩阵变换中,每个点对应着一个4x4的矩阵。如图1-7.在核心动画中transform表明着CATransform3D类型。幸运的是,咱们不须要直接修改这个4x4的矩阵来执行标准的转换;核心动画提供一个全面的函数集合,包含操做有scale,translation,rotation矩阵以及矩阵的比较。除了使用函数操做矩阵以外,核心动画也扩展了KVC,以便于支持咱们使用key paths修改transform。能够经过key paths修改的列表参见CATransform3D Key Paths

Figure 1-7  Converting a coordinate using matrix math


图1-8展示了常见的transformations的矩阵配置。任何乘以identity矩阵的coordinate将不会变化,当乘以其余矩阵时,coordinate的变化和矩阵每一个份量都有关。例如,沿着X轴平移,咱们须要提供非零的 tx 份量并让 ty 和 tz 为0。对于旋转操做,咱们应该提供合适的 sine 和 cosine 值。

Figure 1-8  Matrix configurations for common transformations

 

关于可用的函数信息和矩阵操做,能够参见Core Animation Function Reference。

 

 图层(layer)树反应动画状态的不一样方面

 

使用核心动画的APP有三种Layer对象集合;在将content显示到屏幕上的任务中,每一个Layer对象集合扮演者不一样的角色。

  ·模型树(model layer tree 也被简称为图层树)是和APP交互最多的。模型树上面的模型对象保存着动画的目标值。不管什么时候咱们要改变一个Layer的属性时,咱们应该使用model对象。

  ·呈现树(presentation tree)包含着正在动画过程当中的值。不管在哪里模型树总包含动画的目标值(最终值),而渲染树反映屏幕上显示的当前值。咱们永远都不要修改呈现树上的对象,而能够借助呈现对象来读取当前动画的值,还能够将该值做为一个新的动画的起点。

  ·渲染树(render tree)内包含的对象执行真正的动画,而且它是核心动画私有的。

每个集合内的Layer对象都想APP内的Views同样是以层级结构组织起来的。事实上,一个为全部Views内嵌Layers的APP中,每一个(图层)树的结构和View的层级结构是一直的。然而,APP能够添加单独的Layer对象(单独的Layer对象是指的没有被关联到view的层次中的),经过这么作咱们能够优化APP的content方面的性能,由于某些content的显示是不须要使用Views的其余功能的。图1-9展现了Layer层次的分解图。在这个例子中window包含一个content View,这个View包含了一个button View和两个单独的Layer对象。每个View包含一个对应的Layer对象,这个Layer对象用于造成Layer层结构的一部分。

Figure 1-9  Layers associated with a window

 

如图1-10所示,每个图层树上的对象都有一个对应的对象在渲染树和呈现树上。和以前提到的同样,APP开发中主要使用图层树中的对象,可是有时能够须要获取渲染树上的对象。尤为是,经过图层树内Layer对象的presentationLayer属性能够获取对应的呈现树上的对象,咱们能够经过获取这个对象读取当前动画过程当中某个属性的值。

                          Figure 1-10  The layer trees for a window

 

重要提醒:咱们应该仅仅在动画执行过程当中获取呈现树上的对象。当一个动画还在执行过程当中,渲染树包含Layer在屏幕上那一瞬间显示的值。这个值是不一样于模型树的,模型树只会反映动画终点状态的值。

 

 Layers和Views 之间的关系

 

Layers不是APP中Views的替代品,也就是说咱们不能建立一个仅仅基于Layer对象的可视化界面。Layers为View提供关键基础。尤为是,Layers让它绘制Views的Content和给Views的ContentView更高效以及更方便,而且可以维持高帧率。然而,有许多事情是Layer是没法作到的,Layers没法处理事件、绘制content、参与响应者链条以及好多其余事情。出于这些缘由,每一个APP必须有一个或更多Views去处理这些交互。

在iOS中,每一个Views默认被嵌入一个对应的Layer对象,可是在OS X中咱们必须本身指定哪些Views应该内建Layer。在OS X v10.8和以后,给全部Views添加Layer才有意义,然而咱们咱们不必这么作,当不是必须及指定layer这种消耗没有保证的时候咱们仍旧能够禁止为Views的Layers添加。Layers确实增长APP的内存,可是Layers带来的优势多余缺点,所以在禁止Layer的支持前最好先测试下APP的性能。

当咱们开启某个View的Layer支持时,就建立了一个被置为layer-backed view。在layer-backed view中,系统是有责任建立该View附属的Layer并同时将建立的Layer与View对应保存。全部的iOS中的Views都是layer-backed ,大部分OS X中的View也是同样的。然而,OS X中,咱们也建立Layer-hosting view,这种View须要咱们本身建立一个Layer,对于这中View,AppKit具备管理他的方式而且在View改变时候不调整它。

提示:对于layer-backed views而言,不管什么时候,都推荐操做View而不是操做他的Layer。在iOS中View仅仅是一个Layer对象的简单包装,所以操做处理Layer一般更好。可是,有些时候在iOS和OS X中直接操做Layer可能不会产生预期的效果。此核心动画编程指南将会指出这些陷阱并提供避免他们的方式。

除了和Views关联的Layers外,咱们也能够建立一个没有对应View的Layer对象。咱们将的Layer对象嵌入到其余Layer对象里,例如嵌入到和View关联的Layer里。咱们尤为可使用单独的Layer做为特殊优化的一部分,例如,若是咱们想要使用一样的图片在许多地方,咱们能够加载这个图片一次,并使它和许多单独的Layer对象关联,并将这些Layer对象添加到图层树上,每个Layer因而就引用这个图片资源而不是尝试去再次建立该图片并拷贝到内存中。

 

关于如何开启Layer的支持,参见Enabling Core Animation Support in Your App。关于如何建立一个Layer对象层次和合适应该建立一个对象层次的建议参见Building a Layer Hierarchy(后续会有译文)。

 

注:后续我将会有新的翻译更新,以为不错的朋友能够暂等下

相关文章
相关标签/搜索