概述
core Animation主要用于iOS和OS X 系统上做图形渲染和动画,你可以给app中的view或者可视元素做动画。绘制动画的每一帧的工作都是core animation 完成的。我们需要做的至少配置一些动画参数,比如起点终点,并且要告诉core Animation 启动就ok了。coreAnimation 会将剩下的工作提交给绘制硬件加速渲染,图形加速渲染可以实现高帧速率和流畅的动画,而且也不会给cpu带来负担。
coreAnimation 位于AppKit 和UIKit 之下,并且集成在了cocoa 和Cocoa Touch 的视图工作流程中。
coreAnimation 也暴露view的一些接口给我们,可以让我们更好的控制动画。
core Animation 管理屏幕显示
这里需要明白,core Animation本身不是一个绘制系统,他只是在硬件上用来合成或者操作app的内容的基础结构。coreAnimation的核心是操作Calayer 对象,我们可以用Calyer对象来管理和操作显示内容。CAlayer可以将我们设置的内容捕获到可以到bitmap 位图中,方便图形硬件处理。
图层修改可以触发动画
我们创建的大多数动画都涉及到到Calayer的属性,比如view,layer的bounds,positon,opacity,transform等,对于大多数这些属性,更改属性值会导致创建隐式动画,layer会将属性值从旧值设置成新值。如果我们想更多的控制生成的动画行为,我们也可以显式的设置这些属性动画。
改变layer 的默认行为
layer的隐式动画是用 action 对象的实现了。我们可以创建自己的action对象来实现自定义动画,也可以用action对象来实现其他类型的行为,然后,将操作对象分配给图层的某个属性。当改属性改变时,coreAnimation 将检索您的操作对象并告诉action 执行操作。
core Animation 基础
core Animation 提供一个通用系统,用于动画view 和别的可视元素。core Animation不能替代view,他是一种技术,能给view提供更好的性能和动画支持。 core Animation依靠缓存view的bitmaps图来实现更好的性能和动画支持。
在某些情况下,我们可能需要考虑如何呈现和管理app coreAnimation缓存的这些内容,大多数情况下不需要考虑。
除了缓存view的bitmaps,core Animation 还定义了一种指定任意可视内容的方法,我们可以将该内容与视图集成,和其他内容一起做动画。
我们可以用Core Animation 为view和可视元素更改动画,大多数动画都与可视对象的属性有关。例如,我们可以用core Animation 为视图的position, size, or opacity.
layer绘制和动画基础
layer是2d 和3d 和核心,与view 一样,layer 管理集合,内容,可视属性等。与view不一样的地方在于,layer不能定义自己的外观。layer只管理与bitmap 相关的状态信息,bitmap 自己仅是view绘制的一个结果,或者一样不可改变的image而已。因此,基于layer主要管理数据,所以layers 可以理解为模型对象。这个概念很重要,因为可以影响动画的行为。
layer-模型对象
大多数layer不会进行实际的绘制,而是捕获app提供的内容并将其缓存成bitmap图,有时候也可以称为backing store(备份?)。当改变layer属性的时候,我们所做的只是更改了layer对象关联的状态信息。当更改触发动画时,core Animation会将图层的位图和状态信息传递给图形硬件,图形硬件会使用新信息渲染位图。如图所示,在硬件中操作bitmap会产生比在软件更快的动画
core Animation 操作的是静态bitmap,所以基于layer的绘制与传统的基于view绘制的技术有很大的不同。
用view绘制的时候,对自身的更改会导致调用drawRect:方法,使用新参数重新绘制。但这种绘制是需要耗费cpu的,因为这种操作是在主线程上使用CPU 完成的。而核心动画通过在硬件中操纵缓存的bitmap来实现相同或者类似的效果而避免消耗cpu的资源。
尽管core Animation 尽可能的使用缓存内容,但是,我们仍然必须提供初始内容并且时时更新才可以。
layer-基础动画
layer对象的数据和状态信息与屏幕上改图层可视化内容是分离的。这种分离提供了一种介入自身的方式,以动画的方式让其layer的旧值转变成新值。例如:更改layer的位置属性,会导致CoreAnimation将图层从当前位置移动到新指定的位置。其他属性也会产生适当的动画。
在动画过程中,CoreAnimation 会在硬件中为您完成所有逐帧绘制。我们只需要设置动画的起始点和终点就可以了,coreAnimation完成剩下的工作。我们也可以根据需求指定自定义计时信息和动画参数。否则使用CoreAnimation的默认值
layer-定义自定义图形
layer的一个功能之一是管理其内容的可视形状。可视形状包含内容的边界,在屏幕的位置以及layer是否需要旋转,缩放,变换信息。与view一样,layer也有frame 和 bounds。可以用position定位其位置。layer也有view不具有的属性,例如anchor point(用于定义操作发生的点)。指定layer的形状有些方面还是和view不太一样的
layer- 坐标系
layer 使用两种坐标系,基于点的坐标系和单位坐标系来指定内容的位置。使用哪种坐标系取决于所传达的信息类型
- 点坐标系:指定直接映射到屏幕坐标的值或者是相对于另一个layer指定的值时。例如layer的poisition属性
- 单位坐标系:当值不与屏幕坐标相关联时使用单位坐标系。例如:anchorPoint
点坐标系一般用于指定layer的大小和位置。bound属性定义了图层本身坐标系和自身大小。positon属性定义图层layer相对于父坐标系的位置。虽然layer有frame属性,其实改属性是positon和bound属性派生出来的。
layer 坐标体系方向始终和底层平台的默认方向匹配。
在iOS中,默认情况下,边界矩形的原点位于图层的左上角,而在OS X中,它位于底部 - 左下角。
上图有个positon属性,定义在layer的中心,该属性的值会因为anchorPoint属性的改变而改变。
anchorPoint 属于单位坐标系,下面是单位坐标系在个平台的方向
ancorPoint 锚点使用
锚点与layer的几何图形有关系。锚点可以影响layer的positon 和 图形变化(放大,缩小等)。position 属性始终相对于layer的锚点指定,并且layer的任何图形变化transform都是基于锚点发生。
下图演示如何将锚点从默认值更改到不同值对layer positon的影响,即使layer没有在super 的bounds内移动,我们将锚点从layer的中心移动到图层的边界,原点也会更改poisition属性中的值
我们将锚点从(0.5,0.5)移动到(0,0),假设layer的位置在屏幕上不变,那么layer的positon 也从(100,100)变成了(40,60)
下图显示锚点如何影响layer的transform。当给layer旋转变换时,旋转会围绕锚点旋转。默认锚点位于中间。
如果我们不改默认anchorPoint 值,positon就相当于UIView的center
如果anchorPoint 是(0,0)positon 就相当于UIView的起始点
layer-三维变换
每个layer 有两个变换矩阵,我们可以用他们来操作layer以及内容。layer的transform应用于layer以及子layer的变换。通常,我们想要修改layer本身时候,可以用改属性。我们可以用sublayerTransform属性定义自图层的转换,最常用于向场景内容透视效果
通常我们将坐标值乘以数字矩阵来变换工作,以获取变换后的新坐标。由于核心动画值可以在三维中指定,因此每个坐标值有四个值,必须乘以一个四乘四的矩阵。在CoreNaimation中,3D变换用CATransform3D 类型标示。我们不必修改次结构的字段执行标准转换,core Animation提供了一整套功能,用于创建缩放,平移和旋转矩阵以及进行矩阵比较。除了使用函数操作变换之外,core Animation 还扩展了键值编码支持,运行我们使用key Paths来修改变换。
下图显示了我们可以进行的一些常见的矩阵变化配置。
layer tree-动画状态的不同方面
使用CoreAnimation 的应用程序有三组layer对象,每组layer对象在显示屏幕内容具有不同的作用
- 在layer Tree中的对象是我们与应用程序交换的对象。在layerTree中的对象存储动画的目标值。当改变layer的一个属性,那意味着改变了layerTree中的一个layer
- presentation layerTree中的layer包含正在运行的动画中的值。layerTree中的layer保存的是目标值,而 presentation layerTree的layer保存的是当前值,我们不应该要改变presentation layerTree 中layer的值。不过,我们可以不可以修改,但可以读取这些值。
- render tree 中执行实际的动画,这些动画是CoreAnimation私有的
每个layer对象都是以分层结构组织起来的,就想view一样。实际上,完全用view创建的应用,view的层次结构和layer的层次结构完全相同。
上图显示了一个app,改app的 window包含一个内容view,该view本身包含一个button和两个独立的layer对象。每个view都有一个对应的layer对象,它构成layer层次结构的一部分。
对应每个layerTree中的对象,都有一个layer与presentation和render tree的对象相匹配。如图所示,app主要使用的layer tree 中的对象,但有时候可能会访问presentation tree中对象。具体来讲,访问 在layer tree中的presentation 层的对象,会返回presentation层中的对象。比如想访问动画执行到中间的当前值。
重要提示
我们访问 presentation tree 的对象仅应该在动画播放的时候访问。当动画正在进行的时候, presentation tree 包含当时在屏幕显示的layer属性当前值。此行为与layer tree不一样,layer tree始终显示的代码设置的最后值,等效于动画的最终状态
layer和view 的关系
layer不是view 的替代品,也就是说,我们没有办法基于layer 创建可视化界面。layer只是为view提供基础结构。具体而言,layer可以更轻松,更高效的绘制和动画视图内容,并且可以保持高帧速度。但是,layer好多事情没有做。layer 不处理时间,绘制内容,参与响应链或者执行许多其他操作。处于这些原因,每个app必须有一个或者多个view来处理这些类型的交互。
在ios中,每个view都有相应的layer相对应。所有ios视图都是图层支持的。
对于支持layer的view,apple建议我们尽量操作view而不是操作layer。在ios中,view只是layer对象的简单封装,一般情况下只要是view能满足条件就是用view吧。除非view不能满足要求,那么就只能是用layer了。
除了与view相关联的layer,我们还可以自己创建没有view的layer,这些layer可以添加到app的任何layer中,包括与view相关联的layer。通常,我们使用单独的layer对象作为特定优化路径的一部分。例如:如果我们要在多个位置使用相同的图像,我们可以加载图像一次,并将其与懂个独立层对象关联,并将这些对象添加到layer tree中。然后,每个层引用源对象,而不是尝试在内存中创建自己的图像副本。