iOS 动画框架
- 从图中可以看出,
iOS
从上层到底层你会接触到 UIKit、Core Animation、Core Graphics
。使用难度依次递增,实现效果的复杂度越来越高
CALager 绘制的子类
- CAShapeLayer:用于绘制曲线等图形
- CATextLayer:用于绘制文字
- CAGradientLayer:用于绘制渐变
UIView和CALayer关系
- UIView 可以
响应事件
;CALayer 不可以
- UIView 主要是对
显示内容的管理
;CALayer 主要侧重 显示内容的绘制
- UIView 是 iOS 平台对
CALayer
的 封装
;CALayer 是 iOS 和 OSX 跨平台的类
- UIView 的很多属性其实是返回
CALayer
的属性,比如 frame、center
等等
导入头文件
UIView的Block动画
UIView
的 Block
动画的适用范围
UIView
的动画可以修改一些 属性
,将其以动画的形式展示出来。可修改的属性如下:frame(尺寸)\bound(大小)\center(中心)\ transform(旋转)\alpha(透明度)\ backgroundColor(背景颜色)\ contentStretch(内容拉伸)
等。
- 使用
UIView
实现普通动画
1 2 3 4 5 6 7 8
| /*! 1、设置动画时间 2、设置动画内容 */ UIView.animate(withDuration:5) { // 位置和颜色的变换 animationView.frame = CGRect.init(x: self.view.frame.width - 200, y: 50, width:100, height: 200) }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| /*! 1、设置动画时间 2、设置动画内容 3、设置动画结束后的处理事件 */ UIView.animate(withDuration: 5, animations: { // 位置和颜色的变换 animationView.frame = CGRect.init(x: 100, y: 50, width: 100, height: 200) }) { (isFinish) in if isFinish { // 变色 self.View1!.backgroundColor = UIColor.magenta } }
|
- 设置动画时间、动画延迟时间、动画内容、动画结束内容的动画函数
1 2 3 4 5 6 7 8 9 10 11 12
| /*! 可设置延时时间的动画 @withDuration : 设置动画时间 @delay : 设置动画延迟时间 @options : 设置动画的形式 */ UIView.animate(withDuration: 5, delay: 2, options: .allowUserInteraction, animations: { // code.... 动画的内容 }) { (isFinish) in // code.... 动画结束后的处理内容 }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| /*! 弹簧式动画 @withDuration : 设置动画时间 @delay : 设置动画延时时间 @usingSpringWithDamping : 设置阻尼系数(该数字越大,动画弹动的次数越少) @initialSpringVelocity : 设置初始速度(该数字越大,震动的振幅越大) @options : 设置动画的出现形式 */ UIView.animate(withDuration: 5, delay: 2, usingSpringWithDamping: 0.1, initialSpringVelocity: 10, options: .curveEaseIn, animations: { // code.... 动画的内容 animationView.frame = CGRect.init(x: (self.View1?.center.x)!-20, y: 110, width: 40, height: 40) }) { (isFinish) in // code.... 动画结束后的处理内容 animationView.frame = CGRect.init(x: self.View1!.center.x-40, y: 110, width: 80, height: 80) }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| /*! 帧动画 @withDuration : 设置动画时间 @delay : 设置动画延迟时间 @options :设置动画形式 */ UIView.animateKeyframes(withDuration: 8, delay: 0, options: .calculationModeLinear, animations: { // code.... 动画的内容 UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 1.0/4, animations: { animationView.backgroundColor = UIColor.red }) UIView.addKeyframe(withRelativeStartTime: 1.0/4, relativeDuration: 1.0/4, animations: { animationView.backgroundColor = UIColor.green }) UIView.addKeyframe(withRelativeStartTime: 2.0/4, relativeDuration: 1.0/4, animations: { animationView.backgroundColor = UIColor.blue }) UIView.addKeyframe(withRelativeStartTime: 3.0/4, relativeDuration: 1.0/4, animations: { animationView.backgroundColor = UIColor.magenta }) UIView.addKeyframe(withRelativeStartTime: 4.0/4, relativeDuration: 1.0/4, animations: { animationView.backgroundColor = UIColor.purple }) }) { (isFinish) in // code.... 动画结束后的处理内容 animationView.backgroundColor = UIColor.cyan }
|
1 2 3 4 5 6 7 8 9
| /*! 帧动画 @withRelativeStartTime : 设置动画的开始时间 @relativeDuration : 动画的持续时间 */ UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 1.0/4, animations: { animationView.backgroundColor = UIColor.purple })
|
- UIView 转场动画
1 2 3 4 5 6 7 8 9 10 11 12
| /*! 单个View的转场动画 @with : 要转场的View @duration : 转场时间 @options : 动画的类型 */ UIView.transition(with: animationView, duration: 5, options:.transitionCurlUp, animations: { self.imageView4?.image = UIImage.init(named: "2.jpg") }) { (isFinsish) in // code .... 转场结束事件处理 }
|
1 2 3 4 5 6 7 8 9 10 11
| /*! 转场动画 @from : 起始View @to : 结束View @duration : 动画时间 @options : 动画的形式 */ UIView.transition(from: fromView, to: toView, duration: 5, options: [ .transitionFlipFromLeft,.showHideTransitionViews]) { (isFinish) in // code .... 两个View的其他处理内容 }
|
- UIView 基本动画写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| // TODO: 动画的一般写法 func basicAnimation() -> Void { // 开始某个动画 UIView.beginAnimations("animation", context: nil) // 设置动画时间 UIView.setAnimationDuration(5) // 设置动画的延时时间 UIView.setAnimationDelay(0.25) // 设置动画的效果 UIView.setAnimationCurve(.easeInOut) // 设置动画是否重复,0为无限重复 UIView.setAnimationRepeatCount(0) // 设置动画的代理 UIView.setAnimationDelegate(self) // 设置动画将要触发的时调用的方法 UIView.setAnimationWillStart(#selector(willStartMethod)) // 设置动画结束时触发的方法 UIView.setAnimationDidStop(#selector(didStopMethod)) // 设置动画是否可用 UIView.setAnimationsEnabled(true) // 设置动画是否从当前状态开始(例如:一个动画正在播放时,我们要进行下一个动画,如果设置为 true 时,动画将从当前动画状态开始动画。为 false时是等上一个动画停止时,开始下一个动画) UIView.setAnimationBeginsFromCurrentState(true) // 设置动画开始的时间 UIView.setAnimationStart(Date.init()) // 设置动画是否执行动画回路,前提 UIView.setAnimationRepeatCount(0) 为 0 UIView.setAnimationRepeatAutoreverses(true) // 设置单个View的转场动画 UIView.setAnimationTransition(.flipFromLeft, for: self.view, cache: true) // 设置动画的结束 UIView.commitAnimations() }
// 动画代理触发事件
@objc func willStartMethod() { // 动画将要开始执行触发的代理事件 }
@objc func didStopMethod() { // 动画结束后触发的方法 }
|
Core Animation 动画
Core Animation
动画的适用场景?
- 当我们无法用
Block
动画解决动画问题时,就是 Core Animation
出场了
- 比如:改变
cornerRadius
,沿着一条曲线移动 view
等等
Core Animation
的所有功能都是基于 layer
对吗?
- 对,都基于
layer
- 当你通过
Core Animation
修改了 layer
的属性时,Core Animation
会通过
GPU
来重新渲染位图,因为是硬件渲染,因此速度非常快。
- 几种常用的
CALayer
子类
CAEmitterLayer
是一个粒子发射器系统,负责粒子的创建和发射源属性的配置。它可以创建出炫酷的粒子效果动画
可以创建色彩渐变的图层效果
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| // 创建图层对象 let gradientLayer = CAGradientLayer() // 设置图层尺寸与位置 gradientLayer.bounds = CGRect(x: 0, y: 100, width: 100, height: 100) gradientLayer.position = CGPoint(x: 100, y: 100) // 设置要进行色彩渐变的颜色 gradientLayer.colors = [UIColor.red.cgColor,UIColor.green.cgColor,UIColor.blue.cgColor] // 设置要进行渐变的临界位置 当红色渲染到1/5后开始向绿色进行渐变,绿色渲染到1/2后开始向蓝色进行渐变,当到达7/10距离后完成渐变过程,开始渲染为纯蓝色 gradientLayer.locations = [NSNumber(value: 0.2),NSNumber(value: 0.5),NSNumber(value: 0.7)] // 设置渐变的起始点与结束点 (0,0)左上角 (1,1)右下角 gradientLayer.startPoint = CGPoint(x: 0, y: 0.5) gradientLayer.endPoint = CGPoint(x: 1, y: 0.5) // 添加视图 self.view.layer.addSublayer(gradientLayer)
|
可以通过 OpenGL ES
来进行界面的绘制
CAReplicatorLayer
是一个图层容器,会对其中的子图层进行复制和属性偏移。可以用来创建类型倒影效果,也可以进行图层的变换复制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| // 创建拷贝图层 let replicatorLayer = CAReplicatorLayer() replicatorLayer.position = CGPoint.zero // 创建内容图层 let subLayer = CALayer() subLayer.bounds = CGRect(x: 0, y: 0, width: 20, height: 20) subLayer.position = CGPoint(x: 30, y: 100) subLayer.backgroundColor = UIColor.red.cgColor replicatorLayer.addSublayer(subLayer) // 设置每次拷贝将副本沿x轴平移30个单位 replicatorLayer.instanceTransform = CATransform3DMakeTranslation(30, 0, 0) // 设置拷贝副本的个数 replicatorLayer.instanceCount = 10 // 添加视图 self.view.layer.addSublayer(replicatorLayer)
|
可以让其管理的多个子层进行滑动,但是只能通过代码进行管理,不能进行用户点按触发
可以在图层上直接绘制出自定义的形状
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| // 创建图层 let shapeLayer = CAShapeLayer() shapeLayer.position = CGPoint.zero // 创建图形路径 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)) // 设置图层路径 shapeLayer.path = path // 设置图形边缘线条起点 shapeLayer.strokeStart = 0 // 设置图形边缘线条终点 shapeLayer.strokeEnd = 1 // 设置填充规则 shapeLayer.fillRule = CAShapeLayerFillRule.evenOdd // 设置填充颜色 shapeLayer.fillColor = UIColor.red.cgColor // 设置边缘线条颜色 shapeLayer.strokeColor = UIColor.blue.cgColor // 设置边缘线条宽度 shapeLayer.lineWidth = 1 self.view.layer.addSublayer(shapeLayer)
|
用于进行文字的绘制
瓦片视图,可以分区域绘制,常用于在一张大的图片中分区域绘制
用于构建一些图层变化效果,包括3D效果的图层变换
- CoreAnimation 框架中的属性动画
CAAnimation
类是 CoreAnimation
子类,主要分为:CAPropertyAnimation
(CABasicAnimation
属性过渡动画、CAKeyframeAnimation
关键帧属性过渡动画)、CATransition
、CAAnimationGroup
1 2 3 4 5 6 7 8 9 10
| // 创建动画实例,keyPath为要进行属性动画的属性路径 transform.rotation.z 表示图形属性中以 z 轴为中心轴的旋转属性 let basicAni = CABasicAnimation(keyPath: "transform.rotation.z") // 从0度开始旋转 basicAni.fromValue = NSNumber(value: 0) // 旋转到180度 basicAni.toValue = NSNumber(value: Double.pi) // 设置动画播放的时长 basicAni.duration = 2 // 将动画作用于当前界面的视图Layer层上 self.view.layer.add(basicAni, forKey: nil)
|
1 2 3 4 5 6 7 8
| // 创建动画实例,keyPath为要进行属性动画的属性路径 transform.rotation.z 表示图形属性中以z轴为中心轴的旋转属性 let keyframeAni = CAKeyframeAnimation(keyPath: "transform.rotation.z") // 从0度开始旋转 keyframeAni.values = [NSNumber(value: 0),NSNumber(value: Double.pi/4),NSNumber(value: 0),NSNumber(value: Double.pi)] // 设置动画播放的时长 keyframeAni.duration = 3 // 将动画作用于当前界面的视图Layer层上 self.view.layer.add(keyframeAni, forKey: "")
|
- CASpringAnimation类似弹簧的阻尼动画
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| // 创建动画实例 let springAni = CASpringAnimation(keyPath: "position.y") // 模拟重物质量,必须大于0,默认为1,会影响惯性 springAni.mass = 2 // 模拟弹簧劲度系数,必须大于0,这个值越大,则回弹越快 springAni.stiffness = 5 // 设置阻尼系数,必须大于0,这个值越大,回弹的幅度越小 springAni.damping = 2 springAni.toValue = 300 springAni.duration = 3 // 创建演示动画的Layer let layer = CALayer() layer.position = CGPoint(x: 100, y: 100) layer.bounds = CGRect(x: 0, y: 0, width: 100, height: 100) layer.backgroundColor = UIColor.red.cgColor self.view.layer.addSublayer(layer) layer.add(springAni, forKey: "")
|
1 2 3 4 5 6 7 8 9 10 11 12
| // 创建转场动画实例 let transAni = CATransition() // 设置转场动画类型 transAni.type = CATransitionType.reveal // 设置转场动画方向 transAni.subtype = CATransitionSubtype.fromTop let layer = CALayer() layer.position = CGPoint(x: 100, y: 100) layer.bounds = CGRect(x: 0, y: 0, width: 100, height: 100) layer.backgroundColor = UIColor.red.cgColor layer.add(transAni, forKey: "") self.view.layer.addSublayer(layer)
|
type转场动画属性
1 2 3 4 5 6 7 8
| // 渐入效果 transAni.type = CATransitionType.fade // 移入效果 transAni.type = CATransitionType.moveIn // 压入效果 transAni.type = CATransitionType.push // 溶解效果 transAni.type = CATransitionType.reveal
|
subtype属性
1 2 3 4 5 6 7 8
| // 从右侧执行 transAni.subtype = CATransitionSubtype.fromRight // 从左侧执行 transAni.subtype = CATransitionSubtype.fromLeft // 从上侧执行 transAni.subtype = CATransitionSubtype.fromTop // 从下侧执行 transAni.subtype = CATransitionSubtype.fromBottom
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| // 创建背景色过渡动画 let basicAni = CABasicAnimation(keyPath: "backgroundColor") basicAni.toValue = UIColor.green.cgColor // 创建形变动画 let basicAni2 = CABasicAnimation(keyPath: "transform.scale.x") basicAni2.toValue = NSNumber(value: 2) // 进行动画组合 let groupAni = CAAnimationGroup() groupAni.animations = [basicAni,basicAni2] groupAni.duration = 3 let layer = CALayer() layer.position = CGPoint(x: 100, y: 100) layer.bounds = CGRect(x: 0, y: 0, width: 100, height: 100) layer.backgroundColor = UIColor.red.cgColor layer.add(groupAni, forKey: "") self.view.layer.addSublayer(layer)
|