Core Animation学习笔记

609 阅读5分钟

引言

Core Animation是iOS和OS X上进行图形渲染和加载动画的基础架构,可用于为视图和应用程序的其他视觉元素设置动画。Core Animation本质是将CALayer的内容转化为位图,进一步将大部分实际绘图工作交给底层专用图形硬件加速渲染,以实现高帧率和流畅的动画,而不会给CPU带来负担并降低应用程序的速度。

当我们在书写iOS App时,不管有没有注意到,实际上都在使用Core Animation。其位于AppKit和UIKit之下,并保有接口用于扩展应用程序视图所暴露的功能,使我们对应用程序的动画有更细粒度的控制。

Core Animation逻辑层级

CALayer

上面提到,Core Animation的本质是对CALayer相关属性进行封装、转化,传递给底层硬件进行渲染展示。因此想要学习应用Core Animation,首先应该对CALayer及其属性有一定了解。

CALayer & UIView

UIView表示屏幕上的一块矩形区域,其继承自UIResponder,因此UIView可以做事件响应,它也是iOS中所有视图(控件)直接或者间接的父类。UIView可以管理矩形区域里的内容,处理矩形区域的事件,包括对子视图的管理以及动画的实现等。

UIKit家族族谱
CALayer跟UIView概念上很相似,同样都是被层级管理树管理的一些矩形块,同样可以包含内容,管理子图层,可以做动画和变换。但是最大的不同是UIView可以处理用户的交互,而CALayer是不能够响应事件的(因为其直接继承自NSObject),即使它提供了一些判断触点是否在图层范围内的方法。每一个UIView视图内部都封装了一个CALayer图层,我们通过UIView的layer属性访问这个图层。其实对于UIView来说负责内容展示的就是它内部的CALayer,UIView只不过是将自身的展示任务交给了内部的CALayer完成,而它还肩负着一些其它的任务,比如说用户的交互响应,提供一些Core Animation底层方法的高级接口等。

隐式动画

当我们改变CALayer的一个可做动画的属性(哪些属性下文会列举),它并不会立刻在屏幕上体现出来,也不是直接“闪现”到新的值。相反,Core Animation会自动为其创建一个时间默认为0.25秒,由先前的值平滑过渡到新的值的动画。这一切都是默认的行为,并不需要做额外的操作。(具体逻辑参见下文——CATransaction事务类)

⚠需️要注意的是,UIView的根layer是不附带隐式动画的。

CALayer Properties

属性 介绍 是否支持隐式动画
boounds 图层大小(相对于self)
position 图层中心点位置(superlayer)
zPosition 图层纵向位置(superlayer)
anchorPoint 锚点,取值范围(0~1,0~1),相对于自身宽高的比例
frame 图层大小和位置(superlayer)
hidden 是否隐藏
superlayer 父图层
sublayers 子图层
mask 图层蒙版
maskToBounds 子图层超出自身部分是否裁剪(默认NO)
contents 图层显示内容
contentsRect 图层显示内容位置大小
backgroundColor 背景色
cornerRadius 圆角半径
borderWidth 边框宽度
borderColor 边框颜色
opacity 透明度
shadowColor 阴影颜色
shadowOpacity 阴影透明度
shadowOffset 阴影偏移
shadowPath 阴影形状
shadowRadius 阴影模糊半径
transform 图层变换
doubleSided 图层背面是否显示(默认YES)

阅读Apple开发文档,以及网上很多博客,其中都认为layer.frame不支持隐式动画,可我在实践调用中发现改变frame也会是平滑的动画过渡,并且本质还是调用了CALayer的setBounds:和setPosition:方法。

Core Animation

Core Animation家族族谱

CAMediaTiming

Methods that model a hierarchical timing system, allowing objects to map time between their parent and local time.

以上是苹果官方对该协议的说明内容,可以看到该协议并不仅仅为动画提供时间、速率等相关属性,更宽泛地理解应该是为分层计时系统建模,允许对象在其父时间和本地时间之间映射时间,可以理解为每一个实现“CAMediaTiming”的对象都有一条自己的时间轴。

CAMediaTiming属性 介绍
beginTime 动画相对于父对象(父图层、父动画)的开始时间,默认为0.0且不会自动变化
durantion 动画持续时间
timeOffset 动画时间偏移量,默认为0.0且不会自动变化。例如设置动画时长为3秒,当设置timeOffset为1.5时,当前动画会从中间位置开始,并在到达终点后,走完之前跳过的前半段动画
speed 动画运行速率,相对于影响动画执行快慢,更应该注意其对当前图层时间轴的影响
repeatCount 动画重复次数
repeatDuration 动画重复时间
autoreverses 播放完自动执行逆动画
fillMode CAMediaTimingFillMode
CAMediaTimingFillMode值 说明
kCAFillModeRemoved 默认值,当动画开始前和动画结束后,动画对layer都没有影响,layer保持之前的状态
kCAFillModeForwards 当动画结束后,layer会一直保持着toValue的状态
kCAFillModeBackwards 动画在开始之前(延迟的这段时间内)显示fromValue的状态
kCAFillModeBoth 上面两个的合成.动画开始之前,layer便处于动画fromValue状态,动画结束后layer保持动画最后的状态

注意必须配合animation.removeOnCompletion = NO才能实现相应效果

CAAnimation