引言
Core Animation是iOS和OS X上进行图形渲染和加载动画的基础架构,可用于为视图和应用程序的其他视觉元素设置动画。Core Animation本质是将CALayer的内容转化为位图,进一步将大部分实际绘图工作交给底层专用图形硬件加速渲染,以实现高帧率和流畅的动画,而不会给CPU带来负担并降低应用程序的速度。
当我们在书写iOS App时,不管有没有注意到,实际上都在使用Core Animation。其位于AppKit和UIKit之下,并保有接口用于扩展应用程序视图所暴露的功能,使我们对应用程序的动画有更细粒度的控制。

CALayer
上面提到,Core Animation的本质是对CALayer相关属性进行封装、转化,传递给底层硬件进行渲染展示。因此想要学习应用Core Animation,首先应该对CALayer及其属性有一定了解。
CALayer & UIView
UIView表示屏幕上的一块矩形区域,其继承自UIResponder,因此UIView可以做事件响应,它也是iOS中所有视图(控件)直接或者间接的父类。UIView可以管理矩形区域里的内容,处理矩形区域的事件,包括对子视图的管理以及动画的实现等。

隐式动画
当我们改变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

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才能实现相应效果