当前位置: 首页 > news >正文

iOS动画相关

App内的动画对于用户体验的提升很重要,在iOS实际开发中常用的动画主要包括两大类,UIView动画和核心动画(Core Animation),Core Animation又分出来CAAnimationGroup(组动画),CABasicAnimation(基本动画),CAKeyframeAnimation(关键帧动画)以及CATransition(转场动画)。

1、UIView动画

UIView类提供了大量的动画API,使用这些UIView提供的类方法我们可以对View的相关属性做动画,包括position,size,bounds&frame,center,backgroundColor,alpha,transformation。对于UIView的animate函数而言,只需在闭包中写入相关的属性及值,则可以进行对应的动画处理,例如:

UIView.animate(withDuration: 0.3, delay: 0.0, options:[UIView.AnimationOptions.allowUserInteraction, UIView.AnimationOptions.beginFromCurrentState], animations: { () -> Void in
      // set your view's attribute you want to change
}) { (_) -> Void in
     //do something after animation completed
}

其中,相关属性说明如下:

  • duration :整个动画持续的时间

  • delay:动画在多久之后开始,值为 0 表示代码执行到这里后动画立刻开始

  • options:一些有关动画的设置,包括淡入淡出,是否允许交互,转场效果等都在options设置

  • animations:在这个 block 中写入你想要执行的代码即可。block 中对视图的动画属性所做的改变都会生成动画

  • completion:动画完成后会调用,finished 表示动画是否成功执行完毕。可以将动画执行完成后需要执行的代码写在这里

类似的方法调用还包括:

//转场动画
open class func transition(with view: UIView, duration: TimeInterval, options: UIView.AnimationOptions = [], animations: (() -> Void)?, completion: ((Bool) -> Void)? = nil)
//关键帧动画
open class func animateKeyframes(withDuration duration: TimeInterval, delay: TimeInterval, options: UIView.KeyframeAnimationOptions = [], animations: @escaping () -> Void, completion: ((Bool) -> Void)? = nil)

2 Core Animation

 

CAAnimation是所有动画对象的父类,负责控制动画的持续时间和速度,是个抽象类,不能直接使用,应该使用继承于CAAnimation的四个子类来实现相关动画。其中关于CAAnimation的一些比较重要的属性有:

  • duration:动画的持续时间

  • repeatCount:默认为0,重复次数,无限循环可以设置greatestFiniteMagnitude

  • repeatDuration:重复时间

  • autoreverses:是否倒退,如果为true,则执行动画后倒退回动画前

  • fillMode:默认为.remove,代表动画执行完毕后就从图层上移除,如果想让图层保持显示动画执行后的状态,那就设置fillMode为.forwards(.backwards, .both分别代表动画前以及动画中间的某一个状态)

  • beginTime:可以用来设置动画延迟执行时间,若想延迟2s,就设置为CACurrentMediaTime()+2,CACurrentMediaTime()为图层的当前时间

  • Speed:速度控制函数,控制动画运行的节奏

  • delegate:动画代理

其中CAAnimation有两个比较重要的代理方法,分别为:

@protocol CAAnimationDelegate <NSObject>
  //动画已经开始
- (void)animationDidStart:(CAAnimation *)anim;
	//动画已经结束或者动画已经从添加的layer中移除
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;

CABasicAnimation(基本动画)

继承于CAPropertyAnimation,用于绘制基础的两帧动画(初始帧跟结束帧),主要属性:

//CAPropertyAnimation属性,要改变的属性名称,字符串
open var keyPath: String?
//keyPath对应的初始值
open var fromValue: Any?
//keyPath对应的结束值
open var toValue: Any?
//keyPath的改变值
open var byValue: Any?

keyPath可以使用的key值有:

transform.rotation.x 围绕x轴翻转 参数:角度 angle2Radian(5) 
transform.rotation.y 围绕y轴翻转 参数:同上 
transform.rotation.z 围绕z轴翻转 参数:同上 
transform.rotation 默认围绕z轴 
transform.scale.x x方向缩放 参数:缩放比例 1.5 
transform.scale.y y方向缩放 参数:同上 
transform.scale.z z方向缩放 参数:同上 
transform.scale 所有方向缩放 参数:同上 
transform.translation.x x方向移动 参数:x轴上的坐标 100 
transform.translation.y x方向移动 参数:y轴上的坐标 
transform.translation.z x方向移动 参数:z轴上的坐标 
transform.translation 移动 参数:移动到的点 (100,100) 
opacity 透明度 参数:透明度 0.5 
backgroundColor 背景颜色 参数:颜色 (id)[[UIColor redColor] CGColor] 
cornerRadius 圆角 参数:圆角半径 5 
borderWidth 边框宽度 参数:边框宽度 5 
bounds 大小 参数:CGRect 
contents 内容 参数:CGImage 
contentsRect 可视内容 参数:CGRect 值是0~1之间的小数 
hidden 是否隐藏 
position 
shadowColor 
shadowOffset 
shadowOpacity 
shadowRadius

随着动画的进行,在长度为duration的持续时间内,keyPath相应属性的值从fromValue渐渐地变为toValue。值得注意的是,以上三个属性均为可选值,三者应满足fromValue + byValue = toValue,设置值时应满足最少两个值不为nil,否则若:

  • fromValue不空:从fromValue到属性的当前值之间插值

  • toValue不空:从属性的当前值到toValue之间插值

  • byValue不空:从属性的当前值插值到当前值加上byValue作为终值

  • 三者全空:从属性的先前值到当前值进行插值

let animationOpacity = CABasicAnimation(keyPath: "opacity")
animationOpacity.fromValue = NSNumber(value: 1.0)
animationOpacity.toValue = NSNumber(value: 0)
animationScale.duration = 0.5
animationOpacity.fillMode = .forwards

CAKeyframeAnimation(关键帧动画)

继承于CAPropertyAnimation,与CABasicAnimation不同的是,关键帧动画存储了在动画过程中的一系列帧,用于实现复杂动画过程。主要属性有:

//保存动画过程中数值的数组,里面的元素称为“关键帧”(keyframe)。动画对象会在指定的时间(duration)内,依次显示values数组中的每一个关键帧
open var values: [Any]?
//代表路径可以设置一个CGPathRef、CGMutablePathRef,让图层按照路径轨迹移动。path只对CALayer的anchorPoint和position起作用。如果设置了path,那么values将被忽略
open var path: CGPath?
//可以为对应的关键帧指定对应的时间点,其取值范围为0到1.0,keyTimes中的每一个时间值都对应values中的每一帧。如果没有设置keyTimes,各个关键帧的时间是平分的
open var keyTimes: [NSNumber]?
let animation = CAKeyframeAnimation.init(keyPath: "transform.rotation")
let value_0 = NSNumber.init(value: -Double.pi / 180 * 8)
let value_1 = NSNumber.init(value: Double.pi / 180 * 8)
animation.values = [value_0, value_1, value_0]
animation.duration = 1.0
animation.repeatCount = 1e100
layer.add(animation, forKey: "animation")

CAAnimationGroup(组动画)

CAAnimationGroup是CAAnimation的子类,可以保存一组动画对象,可以保存基础动画、关键帧动画,数组中的所有动画对象可以同时并发运行,也可以设置为串行连续动画。

let animation1 = CABasicAnimation(keyPath: "position")
animation1.fromValue = [originalFrame!.midX, originalFrame!.midY]
animation1.toValue = [window.frame.midX, window.frame.midY]
animation1.duration = 2
animation1.isRemovedOnCompletion = false
animation1.beginTime = 0.0
animation1.fillMode = .forwards

let animation2 = CABasicAnimation(keyPath: "transform.scale.x")
animation2.fromValue = originalFrame!.width / imageView.frame.width
animation2.toValue = 1.0
animation2.duration = 2
animation2.isRemovedOnCompletion = false
animation2.beginTime = 0.0
animation2.fillMode = .forwards

let animation3 = CABasicAnimation(keyPath: "transform.scale.y")
animation3.fromValue = originalFrame!.height / imageView.frame.height
animation3.toValue = 1.0
animation3.duration = 2
animation3.isRemovedOnCompletion = false
animation3.beginTime = 0.0
animation3.fillMode = .forwards

let group = CAAnimationGroup()
group.animations = [animation1, animation2, animation3]
group.duration = 2
group.isRemovedOnCompletion = false

layer.add(group, forKey: "animation")

CATransition(转场动画)

CATransition是CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。UINavigationController就是通过CATransition实现了将控制器的视图推入屏幕的动画效果,相关属性有:

  • type:动画过渡类型,Apple提供了四种动画过渡类型,为fade(淡出)、moveIn(覆盖原图)、push(推出)以及reveal(从底部显示出来)

  • subtype:动画过渡方向

  • startProgress:动画起点(在整体动画的百分比,范围0~1)

  • endProgress:动画终点(在整体动画的百分比,范围0~1)

let animation = CATransition()
animation.type = .fade
animation.subtype = .fromRight
animation.startProgress = 0
layer.add(animation, forKey: "animation")

补充:每一个UIView内部都默认关联着一个CALayer,称为root layer,所有的非root layer,也就是手动创建的CALayer对象,都存在隐式动画,当对非root layer的部分属性进行修改时,默认会自动产生一些动画效果,而这些属性成为Animation Properties(可动画属性),常见可动画属性:

bounds:用于设置CALayer的宽度和高度。修改这个属性会产生缩放动画
backgroundColor:用于设置CALayer的背景色。修改这个属性会产生背景色的渐变动画
position:用于设置CALayer的位置。修改这个属性会产生平移动画

这里引入一个事务(Transaction)的概念,Core Animation用来包含一系列属性动画集合的机制,通过指定事务来改变图层的可动画属性,而这些改变不是立刻发生,只有在事务被提交的时候才启动一个动画过度到新值,任何可以做动画的图层属性都会被添加到栈顶的事务。

现在再来考虑隐式动画,其实是Core Animation在每个RunLoop周期中会自动开始一次新的事务,即使你不显式的使用CATransaction.begin()开始一次事务,任何在一次RunLoop运行时循环中属性的改变都会被集中起来,执行默认0.25秒的动画。

可以通过以下方法关闭隐式动画:

CATransaction.begin() //动画属性的入栈
CATransaction.setDisableActions(true) //设置隐藏动画
// code that modifies the properties of one or more views.
CATransaction.commit() //动画属性的出栈

参考:

Apple Developer Documentation

iOS动画全面解析 - 掘金

https://www.jianshu.com/p/f2def3da931f

https://www.jianshu.com/p/9fa025c42261

https://www.jianshu.com/p/5abc038e4d94

iOS动画-CALayer隐式动画原理与特性 - 腾讯云开发者社区-腾讯云

https://www.jianshu.com/p/c22918a5e7ca

iOS UIView Animation - Keyframe | 程序员说

https://shixiong.name/2016/11/03/bezier-zhibei/index.html

10.2 自定义缓冲函数 · ios核心动画高级技巧 · 看云

相关文章:

  • LeetCode往完全二叉树添加节点
  • Linux、docker、kubernetes、MySql、Shell运维快餐
  • 基数(桶)排序算法详解之C语言版
  • 生成模型的中Attention Mask说明
  • java毕业设计企业固定资产管理系统源码+lw文档+mybatis+系统+mysql数据库+调试
  • Java---Java Web---JSP
  • opencv 机器学习-人脸识别
  • JavaScript的函数
  • java基于springboot+vue基本微信小程序的乒乓球课程管理系统 uniapp小程序
  • 安装数据库中间件——Mycat
  • 爬虫之Scrapy框架
  • 哈工大李治军老师操作系统笔记【23】:内存换出(Learning OS Concepts By Coding Them !)
  • Ubuntu 20.04 设置开机自启脚本
  • Vue2封装评论组件详细讲解
  • java-php-python-springboot校园新闻趣事计算机毕业设计
  • Android 控件背景颜色处理
  • CSS 专业技巧
  • HTTP 简介
  • Mysql5.6主从复制
  • Rancher如何对接Ceph-RBD块存储
  • ReactNativeweexDeviceOne对比
  • SegmentFault 技术周刊 Vol.27 - Git 学习宝典:程序员走江湖必备
  • vue中实现单选
  • 闭包,sync使用细节
  • 扫描识别控件Dynamic Web TWAIN v12.2发布,改进SSL证书
  • 系统认识JavaScript正则表达式
  • 用mpvue开发微信小程序
  • 在electron中实现跨域请求,无需更改服务器端设置
  • 第二十章:异步和文件I/O.(二十三)
  • ​LeetCode解法汇总2583. 二叉树中的第 K 大层和
  • #Z0458. 树的中心2
  • #快捷键# 大学四年我常用的软件快捷键大全,教你成为电脑高手!!
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • (2)(2.4) TerraRanger Tower/Tower EVO(360度)
  • (c语言版)滑动窗口 给定一个字符串,只包含字母和数字,按要求找出字符串中的最长(连续)子串的长度
  • (pojstep1.3.1)1017(构造法模拟)
  • (Spark3.2.0)Spark SQL 初探: 使用大数据分析2000万KF数据
  • (二)windows配置JDK环境
  • (黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
  • (接口封装)
  • (十三)Java springcloud B2B2C o2o多用户商城 springcloud架构 - SSO单点登录之OAuth2.0 根据token获取用户信息(4)...
  • (转)setTimeout 和 setInterval 的区别
  • .apk 成为历史!
  • .NET 4.0网络开发入门之旅-- 我在“网” 中央(下)
  • .NET Core 项目指定SDK版本
  • .NET版Word处理控件Aspose.words功能演示:在ASP.NET MVC中创建MS Word编辑器
  • .net获取当前url各种属性(文件名、参数、域名 等)的方法
  • .net利用SQLBulkCopy进行数据库之间的大批量数据传递
  • .NET企业级应用架构设计系列之应用服务器
  • .Net中间语言BeforeFieldInit
  • .net中我喜欢的两种验证码
  • [2009][note]构成理想导体超材料的有源THz欺骗表面等离子激元开关——
  • [20180129]bash显示path环境变量.txt
  • [2544]最短路 (两种算法)(HDU)
  • [AutoSar NVM] 存储架构