CALayer知识梳理

2015-09-18  本文已影响187人  jackjhu

关于Core Animation API怎么使用的文章很多,例如下面这些都写的非常好。

ojbc中国#12动画

我这篇文章主要解释一下动画的本质是什么,不涉及太多具体使用。

iOS动画的本质

CALayer是动画产生作用的地方,CALayer是什么鬼呢?看名字像是个Photoshop中的那种图层的概念。在iOS中,一个Layer『本文中的Layer指的是CALayer或它的子类』对象看起来就像一个在3D空间的2D图像显示,为什么说在3D空间呢?因为你可以通过矩阵运算对这个Layer画面进行三纬的翻转,平移、缩放等当然也都不在话下。Layer是你通过Core Animation做的所有事情的核心。

与视图一样,Layer管理着几何信息(位置和大小等)、内容和与显示相关的属性信息。

与视图不同的是,Layer没有定义他自己的外观。

一个Layer仅仅是管理这它的位图(bitmap)相关的状态信息,这个位图可以是它的delegate view的drawRect:方法绘制的,或者你直接设置的一个静态图片信息。

基于这个原因,在app中使用大多数layer都可以被认定是模型(model)对象,因为他们主要是管理数据。这个概念比较重要,因为它影响这动画的行为。你务必要理解,当把动画添加到一个layer时,是不直接修改model的属性的。

取而代之的是,Core Animation维护了两个平行的layer层次结构,model layer tree(模型层树)和presentation layer tree(表示层树)。前者为model的实际属性值,后者为动画正在发生时刻的当前属性近似值(因为动画的属性插值为离散的)。如果要获取某个触发动画的属性在动画过程中的任意值,你需要通过presentation layer的属性获取。

事实上还有一个rendering tree,动画的实际执行,由于是Core Animation私有,这里不解释。

基于Layer的绘图模型

说到Layer的绘图,实际上你app中的大多数layers不会做任何内容绘制的,取而代之的是捕捉你的app提供给他的内容(UIView绘制或者设置contents),然后将它们缓存为位图(bitmap),就是我们常提到的视图的图像后备存储(backing store)。当你随后改变了layer的某个属性,实际就是修改了layer model的状态信息,如果这个动作触发了动画,那么Core Animation会将layer的位图和新的状态信息传给图像处理硬件(通常指GPU),它会根据新的状态信息渲染位图。通过GPU直接操作位图要比使用CPU通过软件绘制要快非常多。

我们可以看到基于Layer的绘图实质上是GPU对静态位图计算操作,这与传统的基于视图的图像绘制有非常显著的差异。

基于视图的绘制,视图的属性变化往往带来的结果是使用不同的参数去调用UIView的drawRect:方法来重绘视图的内容。通过这个方式绘制是非常昂贵的,因为它是使用主线程的CPU来完成的。

Core Animation尽可能的通过硬件对位图的操作来达到相同或者近似的结果来避免上述问题。

你能通过3种方式给Layer提供content内容:

基于Layer的动画

Layer的真实数据和状态信息是与在屏幕上的视觉展示相剥离的。就是说Core Animation维护了两个平行的Layer层次结构,model layer tree和presentation layer tree。这种机制使Core Animation能够在新旧状态间进行插值和动画过渡。

在动画的过程中,Core Animation通过硬件为你完成动画过程中每一帧图像的绘制。而你所需要做的仅仅是告诉它动画的开始和结束状态,其他的都交给Core Animation去完成。当然如果你开心,你也可以指定一些动画参数,例如动画时间、插值计算的timeFunction等参数。

Layer的几何属性

layer_geometry.png

主要涉及3个属性:bounds、position和anchorPoint。

bounds:与UIView类似,origin属性影响子Layers,(0,0)为子Layers布局的坐标参考原点。
size为大小。

anchorPoint:定义了一个锚点,类似被图钉在墙上的一张纸,纸的旋转是以它为中心的。值为相对自身几何体系。值范围为0到1,默认在中心处(0.5,0.5)

position:anchorPoint相对与layer的坐标系的坐标(与anchorPoint实质是同一个点,参考不同坐标系)。

注意:UIView的frame就是简单的读取至它的root layer。

Layer与View的关系

从我们上文的介绍,我们可以认识到。Layer为view相对于为提供了基础设施服务,具体来说就是Layer让view能以较高的帧数和效率对其内容进行重绘和动画。

但是,Layer有很多事不能做,Layer不能处理事件、绘制内容、参与响应链和很多其他事情。因此,你的app至少得有一个或多个view来处理这类交互。

在iOS中,每个view背后都一个对象的layer对象(view背后的女人_),这样的view被称为layer-backed view。view为此layer的delegate,为它提供显示内容和对决定如何对属性变化进行动画的处理(- actionForLayer:forKey:)。例如我们修改view的root layer的属性,没有隐式动画产生,就是因为view作为它的delegate关闭了此场景下的『隐式动画』(但放在动画block中又会自动开启)。

当然layer不是一定要关联view才能存在,你可以创建一个没有view与之对应的layer。然后把它添加到你喜欢的layer中作为子layer。

动画接口API

iOS为我们提供了两套动画的API,一种是Core Animation的,另一种是UIView的动画block。这两者又有何异同呢?
实质上是一样的,UIView的block的动画就是对Core Animation的封装,方便我们使用。当然直接使用更底层的接口,能做出更加丰富的动画效果。

没图说个什么鬼

最后上一张CALayer的梳理图:

CALayer.png
上一篇下一篇

猜你喜欢

热点阅读