## 6.5 核心动画编程技术/u2014/u2014CoreAnimation 在前面章节中介绍了有关UIView层的过渡动画与转场动画的应用/uff0c使用UIView类有关动画的类方法基本可以满足开发中遇到的大部分需求。然而/uff0cUIView层的动画仍然有许多局限性/uff0c开发者若想更加自由地进行iOS动画编程还需要使用一个更加底层也更加强大的框架/uff1aCoreAnimation。 CoreAnimation框架也被称为核心动画编程框架/uff0c它是基于OpenGL与CoreGraphics图像处理框架的一个跨平台的动画框架。如图6-4所示描述了CoreAnimation框架的系统结构。 ![](https://cocosbcx.oss-cn-beijing.aliyuncs.com/article/201909041535305938) 图6-4 CoreAnimation框架的系统结构 CoreAnimation框架中大多数的动画效果都是基于CALayer类来实现的。任何一个UIView视图中都包含了一个CALayer属性/uff0cCALayer对象负责UIView视图的渲染与层级结构。其实CALayer对读者来说并不陌生/uff0c在第2章中进行视图控件的圆角、边框、阴影等操作的时候就已经使用了Layer层的属性。 ### 6.5.1 锚点对视图控件几何位置的影响 CoreAnimation的动画开发是基于Layer层的/uff0c要了解CALayer类的使用/uff0c首先应该先了解一个概念/uff1a锚点。 所有的CALayer对象都有一个anchorPoint属性/uff0c这个属性就是CALayer对象的锚点/uff0c是CGPoint类型。锚点可以理解为对象动作的参照点/uff0c其x/uff0cy值的取值范围都是0/uff5e1。CALayer对象默认的锚点值为(0,0)/uff0c即Layer层的左上角/uff0c如果要将锚点设置Layer层的中心/uff0c则可以设置anchorPoint的值为(0.5,0.5)。当CALayer层进行动作操作时/uff0c执行的动作将以锚点作为参照点/uff0c例如进行旋转、平移等操作。图6-5与图6-6所示为设置不同位置锚点的CALayer对象。 ![](https://cocosbcx.oss-cn-beijing.aliyuncs.com/article/201909041536018206) 图6-5 设置锚点为(0.5/uff0c0.5) ![](https://cocosbcx.oss-cn-beijing.aliyuncs.com/article/201909041536215281) 图6-6 设置锚点为(0,0) 当对图6-5与图6-6中的视图进行旋转操作时/uff0c效果如图6-7与图6-8所示。 ![](https://cocosbcx.oss-cn-beijing.aliyuncs.com/article/201909041536522947) 图6-7 以视图中心为锚点进行旋转 ![](https://cocosbcx.oss-cn-beijing.aliyuncs.com/article/201909041537151540) 图6-8 以视图左上角为锚点进行旋转 当一个UIView对象被创建出来后/uff0c其内部自带一个CALayer对象/uff0cLayer层中主要保存视图的绘制信息/uff0cView层则除了整合视图的绘制外/uff0c还封装了接收事件与处理用户交互的功能。 ### 6.5.2 色彩梯度层/u2014/u2014CAGradientLayer CAGradientLayer类是继承于CALayer类的子类/uff0c专门用来创建颜色梯度渐变的视图效果。 使用Xcode开发工具创建一个名为CAGradientLayerTest的工程/uff0c在ViewController类的viewDidLoad方法中添加如下代码。 ```objective-c override func viewDidLoad() { super.viewDidLoad() let layer = CAGradientLayer() layer.colors = [UIColor.red.cgColor,UIColor.blue.cgColor] layer.bounds = CGRect(x: 0, y: 0, width: 100, height: 100) layer.position = CGPoint(x: 100, y: 100) layer.locations = [0.2] layer.startPoint = CGPoint(x: 0, y: 0) layer.endPoint = CGPoint(x: 1, y: 1) self.view.layer.addSublayer(layer) } ``` 上面代码中/uff0cCAGradientLayer对象的colors属性用于设置一个颜色梯度数组。bounds属性是CALayer类的基础属性/uff0c用于设置Layer层的尺寸。position属性是CALayer对象用来确定位置的属性/uff0c其需要设置一个CGPoint类型的值来确定一个点/uff0cposition属性的参照点也与Layer层的锚点有关。locations属性设置色阶梯度的分界线/uff0c需要设置成一个数组/uff0c数组中元素均为0/uff5e1之间并且递增的数值/uff0c例如上面代码将其色阶梯度分界线设置为0.2/uff0c则红色会渲染Layer层20%尺寸后才开始进行向蓝色渐变的梯度变化。CAGradientLayer对象的startPoint与endPoint属性分别设置色阶梯度渲染的起始点与结束点/uff0c通过这两个属性可以确定色阶梯度渐变的方向。例如上面代码将起始点设置为(0,0)/uff0c结束点设置为(1,1)/uff0c则颜色从Layer层的左上角开始渲染到右下角结束/uff0c按左上角到右下角的对角线为渲染方向。 运行工程/uff0c效果如图6-9所示。 ![](https://cocosbcx.oss-cn-beijing.aliyuncs.com/article/201909041538115443) 图6-9 使用CAGradientLayer类创建的色阶梯度视图层 ### 6.5.3 视图拷贝层/u2014/u2014CAReplicatorLayer CARepliccatorLayer类可以理解为一个Layer层拷贝容器/uff0c其作用并非是进行具体某一种视图的展现/uff0c而是拷贝一个已经存在的Layer层对象进行复制渲染。 使用Xcode开发工具创建一个名为CAReplicatorLayerTest的工程/uff0c在ViewController类的viewDidLoad方法中添加如下代码。 ```objective-c override func viewDidLoad() { super.viewDidLoad() let layer = CALayer() layer.bounds = CGRect(x: 0, y: 0, width: 50, height: 50) layer.position = CGPoint(x: 50, y: 100) layer.backgroundColor = UIColor.red.cgColor //创建拷贝容器 let reLayer = CAReplicatorLayer() reLayer.instanceRedOffset = -0.2; reLayer.position = CGPoint(x: 0, y: 0) reLayer.instanceTransform = CATransform3DMakeTranslation(100, 0, 0) reLayer.instanceCount = 3 reLayer.addSublayer(layer) self.view.layer.addSublayer(reLayer) } ``` 上面代码中先创建了一个普通的Layer层作为要拷贝的原本/uff0c将其作为子Layer添加进CAReplicatorLayer对象中。CAReplicatorLayer对象的instanceRedOffSet属性设置每个拷贝的副本背景色中红基色的偏移量/uff0c与其对应的还有instanceGreenOffset,instanceBlueOffset/uff0c instanceAlphaOffset属性分别设置背景色中蓝基色、绿基色和透明度的偏移量。instanceTransform属性设置拷贝视图的3D变化属性/uff0c上面代码设置的CATransform3DTranslation(100,0,0)的意义为将每个拷贝Layer层沿x轴正方向移动100个单位。instanceCount属性设置加上原本要拷贝出的层视图个数。 运行工程/uff0c效果如图6-10所示。 ![](https://cocosbcx.oss-cn-beijing.aliyuncs.com/article/201909041538493558) 图6-10 使用CARelicatorLayer类创建的Layer拷贝视图层 ### 6.5.4 图形渲染层/u2014/u2014CAShapeLayer CAShapeLayer是用于绘制图形的Layer层的/uff0c开发者可以使用它进行自定义的图形绘制。 使用Xcode开发工具创建一个名为CAShapeLayerTest的工程/uff0c在ViewController类的viewDidLoad方法中添加如下代码。 ```objective-c override func viewDidLoad() { super.viewDidLoad() let layer = CAShapeLayer() layer.position = CGPoint(x: 0, y: 0) let path = CGMutablePath() path.move(to: CGPoint(x: 100, y: 100)) path.addLine(to: CGPoint(x: 300, y: 100)) path.addLine(to: CGPoint(x: 200, y: 200)) path.addLine(to: CGPoint(x: 100, y: 100)) layer.path = path layer.strokeColor = UIColor.black.cgColor self.view.layer.addSublayer(layer) } ``` CAShapeLayer对象的path属性用于设置图层的绘制路径/uff0c通过上面代码的设置将在屏幕上绘制一个三角形的Layer层/uff0c运行工程/uff0c效果如图6-11所示。 ![](https://cocosbcx.oss-cn-beijing.aliyuncs.com/article/201909041539286668) 图6-11 CAShapeLayer层绘制的三角形 CAShapeLayer类中还有许多方法用来绘制的图案进行自定义设置/uff0c示例代码如下/uff1a ```objective-c layer.fillColor = UIColor.red.cgColor layer.strokeColor = UIColor.blue.cgColor layer.strokeStart = 0.3 layer.strokeEnd = 0.8 layer.lineWidth = 4 ``` fillColor属性用于设置图形的填充颜色/uff0cstrokeColor属性用于设置图形的边框线条颜色/uff0cstrokeStart属性用于设置线条的起点/uff0c这个值是一个比例值/uff0c为占周长的比例/uff0cstrokeEnd属性设置线条结束的终点/uff0clineWidth属性设置边框线条的宽度。再次运行工程/uff0c效果如图6-12所示。 ![](https://cocosbcx.oss-cn-beijing.aliyuncs.com/article/201909041540049154) 图6-12 为CAShapeLayer绘制的图形进行自定义设置 ### 6.5.5 文本绘制层/u2014/u2014CATextLayer CATextLayer用于进行视图上文本的绘制/uff0cUIKit框架中最基础的UILabel控件就是基于CATextLayer实现的。使用Xcode开发工具创建一个名为CATextLayerTest的工程/uff0c在ViewController类的viewDidLoad方法中添加如下代码。 ```objective-c override func viewDidLoad() { super.viewDidLoad() let layer = CATextLayer() layer.bounds = CGRect(x: 0, y: 0, width: 320, height: 100) layer.position = CGPoint(x: 160, y: 100) layer.string = "我是文字Layer" layer.fontSize = 25 layer.foregroundColor = UIColor.red.cgColor layer.alignmentMode = kCAAlignmentCenter self.view.layer.addSublayer(layer) } ``` 上面代码中/uff0cCATextLayer的string属性用于设置要显示的文字/uff0cfontSize属性设置显示文字的字号/uff0cforegroundColor属性设置文字的颜色/uff0calignmentMode属性设置文字的对齐模式。运行工程/uff0c效果如图6-13所示。 ![](https://cocosbcx.oss-cn-beijing.aliyuncs.com/article/201909041541386258) 图6-13 CATextLayer创建的渲染文本的Layer层 除了上面介绍的这些Layer层类/uff0cCALayer家族中还有一个十分强大的类CAEmitterLayer/uff0c专门用来处理一些粒子效果生成的动画/uff0c因其比较复杂/uff0c将安排在后面章节单独进行介绍。 ### 6.5.6 CAAnimation动画体系介绍 通过前面几个小节的介绍/uff0c读者可以了解到/uff0c通过CALayer开发者可以设置许多视图UI上的属性/uff0cCAAnimation框架的作用就是将这些属性的变化都以动画的形式展现出来。由于CALayer相对于UIView可以更灵活地设置更多属性/uff0c所以对于CALayer层的动画操作也会更加灵活自由。 CoreAnimation框架中的核心类是CAAnimation/uff0cCAAnimation是动画操作的基类/uff0c开发者主要使用一些继承自它的子类来进行CALayer层动画的开发。如图6-14所示为CAAnimation及其子类的关系结构图。 ![](https://cocosbcx.oss-cn-beijing.aliyuncs.com/article/201909041542059124) 图6-14 CAAnimation及其子类结构图 CAAnimation类分出的3个子类CAPropertyAnimation、CAAnimationGroup、CATransition分别用来处理3种不同类型的动画。CAPropertyAnimation最为常用/uff0c视图属性的改变都可以由它来进行动画展示。CAAnimationGroup类用于创建组合动画。CATransition用来创建转场动画。关于CAPropertyAnimation/uff0c它又分出两个子类/uff0cCABasicAnimation和CAKeyframeAnimation/uff0c这两个子类分别用来处理基础类的动画和关键帧类的动画。在基础动画CABasicAnimation中又分出一个子类CASpringAnimation专门用来创建阻尼动画。 CAAnimation类主要定义了所有动画操作都会有的共有属性/uff0c主要有如下两个属性/uff1a ```objective-c //动画执行的时序模式 open var timingFunction: CAMediaTimingFunction? //是否动画完成时将动画对象移除 open var isRemovedOnCompletion: Bool ``` timingFunction属性设置动画执行的时间函数/uff0cremovedOnCompletion用于设置当动画播放完成后是否将动画对象从CALayer上除掉。timingFunction属性可设的参数值如下所示/uff1a ```objective-c //线性执行 public let kCAMediaTimingFunctionLinear: String //淡入 在动画开始时 淡入效果 public let kCAMediaTimingFunctionEaseIn: String //淡出 在动画结束时 淡出效果 public let kCAMediaTimingFunctionEaseOut: String //淡入淡出 public let kCAMediaTimingFunctionEaseInEaseOut: String //默认效果 public let kCAMediaTimingFunctionDefault: String ``` 使用如下的示例代码方法进行CAMediaTimingFunction对象的创建。 ```objective-c CAMediaTimingFunction(name: kCAMediaTimingFunctionDefault) ``` CAPropertyAnimation类中封装了用于属性变化的动画的基类属性/uff0c主要代码如下/uff1a ```objective-c public convenience init(keyPath path: String?) open var isAdditive: Bool open var isCumulative: Bool open var valueFunction: CAValueFunction? ``` 在上面的方法和属性中/uff0canimationWithKeyPath方法用于创建并初始化动画对象/uff0c其中path参数即为要执行动画的属性。例如如果要执行背景色渐变的动画/uff0c则path可设置为字符串backgroundColor。additive设置动画执行的状态是否叠加/uff0c如果设置为布尔值假/uff0c当执行移动动画时/uff0c如果执行两次/uff0c两次动画都会从视图的原始位置进行移动/uff0c如果设置布尔值真/uff0c则第2次移动动画的起点会从第1次移动的终点开始。cumulative属性与重复执行的动画有关/uff0c如果设置为布尔值假/uff0c则重复动画每次执行都会从原始状态开始执行/uff0c设置为布尔值真则重复动画的每次效果都会叠加。ValueFunction这个属性比较特殊/uff0c其专门用来处理transform变换类的动画/uff0c在后面小节的应用中会向读者详细介绍这个属性的应用。 ### 6.5.7 使用CABasicAnimation创建基础动画 前面小节介绍了许多基础知识/uff0c从CALayer层的基本用法到CAAnimation的基类属性。从本节开始将进行一些CoreAnimation动画开发的实践操练。CABasicAnimation是CoreAnimation动画框架中最常用的动画执行类。使用Xcode开发工具创建一个名为CABasicAnimationTest的工程/uff0c在ViewController类中声明一个CALayer类的对象/uff0c如下所示/uff1a ```objective-c private var layer:CALayer? ``` 在viewDidLoad方法中进行layer属性的创建和初始化相关操作/uff0c如下所示/uff1a ```objective-c override func viewDidLoad() { super.viewDidLoad() layer = CALayer() layer?.bounds = CGRect(x: 0, y: 0, width: 100, height: 100) layer?.position = CGPoint(x: 160, y: 100) layer?.backgroundColor = UIColor.red.cgColor self.view.layer.addSublayer(layer!) } ``` 在ViewController类中实现touchesBegan方法/uff0c如下所示/uff1a ```objective-c override func touchesBegan(_ touches: Set
本文由 投稿者 创作,文章地址:https://blog.isoyu.com/archives/6-5-hexindonghuabianchengjishucoreanimation.html
采用知识共享署名4.0 国际许可协议进行许可。除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。最后编辑时间为:9月 4, 2019 at 08:41 下午