十二.核心动画 - 动画缓冲①(框架提供的缓存函数)

引言

上一篇博客我们已经讨论了Core Animation中时间的处理,以及CAMediaTiming协议。本篇博客我们就来看一下另外一个和时间有关的机制--缓冲。

缓冲会让动画看起来更平滑更自然,我们在本篇博客将会体验一下CAAnimation提供的缓存函数,UIView提供的缓存函数,以及关键帧动画如何设置缓冲函数。

动画缓冲

动画速度

说到缓冲我们不得不提到速度,对于物体来讲我们都知道速度=距离/时间,对于动画也是一样的。

velocity = change / time

只不过移动距离替换为了外观的变化,时长就还是值动画一次迭代的时长。

例如说我们给position做动画,这个例子很形象,和物体移动几乎一样,但是实际上它可以是任何东湖,比如颜色,比如透明度,比如旋转角度。

但是上面的等式其实及基于一个假设,假设动画在执行的过程中速度都是恒定不变的,这种恒定速度的动画我们称之为“线性动画”,这是动画缓冲里面最简单的一种,但是呢也最不真实。

无论是行驶的小汽车还是掉落的小球事实上它都不会从一开始到结束都以相同的速度前进,那小汽车来说,通常来讲它的速度应该是从0逐渐增加然后再保持匀速,快要到达终点时再逐渐减小到0。

那么在动画中我们该如下实现这种效果呢,看起来需要通过物理引擎来模拟这些东西,听来有点复杂,不过事实上Core Animation内嵌了一些列的标准缓冲函数,我们可以直接使用它们来达到想要的效果。

CAMediaTimingFunction

为了使用 Core Animation 提供的缓动函数,我们需要设置 CAAnimation 的 timingFunction 属性。timingFunction 是 CAMediaTimingFunction 类型,并且提供了一个非常简便的初始化方法。

public convenience init(name: CAMediaTimingFunctionName)

CAMediaTimingFunctionName有以下五个类型:

  1. .linear:创建一个线性的计时函数,默认类型,适用那些保持匀速运动的物体。
  2. .easeIn:创建一个慢慢加速,然后突然停止的缓冲函数,它对于一个自由落体或者是发射子弹打击目标来说很适用。
  3. .easeOut:和.easeIn相反,一开始全速然后慢慢减速到停止,有一个削弱的过程,适合关门这样的场景。
  4. .easeInEaseOut:创建一个慢慢加速然后再慢慢减速的缓存函数,通常的动画我们都会采用这个函数。
  5. .default:其实它和.easeInEaseOut非常类似,只不过它的加速和减速的过程都稍微慢一些。

这里面为什么叫做default但它又不是默认值呢,其实如果我们显式的创建CAAnimation时,.linear为默认选项,但是当我们不创建CAAnimation,图层的默认动画缓冲则是.default类型。

下面我们来写一个简单的案例,体会一下缓冲函数的作用,代码如下:

    override func viewDidLoad() {super.viewDidLoad()// Do any additional setup after loading the view.timeFunction()}let colorLayer = CALayer()func timeFunction()  {self.view.layer.addSublayer(colorLayer)colorLayer.frame = CGRect(x: 50, y: 50, width: 100, height: 100)colorLayer.backgroundColor = UIColor.red.cgColor}override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {CATransaction.begin()CATransaction.setAnimationDuration(1.0)CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut))colorLayer.position = touches.first!.location(in: self.view)CATransaction.commit()}

效果如下:

案例中我们采用了隐式动画设置缓冲函数,显式动画也是一样的代码如下:

        let animation = CABasicAnimation()animation.keyPath = "transform.position"animation.toValue = NSValue(cgPoint: touches.first!.location(in: self.view))animation.duration = 2.0animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)colorLayer.add(animation, forKey: nil)

UIKit 中的动画缓冲

我们在使用UIView的类方法给视图添加动画时,其中有一个options可选参数,不过之前我们并没有注意到它。事实上它就是UIKit为我们提供的动画缓存函数,有以下几个可以选择的类型:

  1. .curveEaseInOut:和图层的.easeInEaseOut对应,慢进慢出。
  2. .curveEaseIn:和图层的.easeIn对应,慢进。
  3. .curveEaseOut:和图层的.easeOut对应,慢出。
  4. .curveLinear:和图层的.linear对应,线性匀速做动画。

注意这里面只有这四个选项,没有与图层.default对应的选项,我们在具体的代码中来体验一下它的效果,代码如下:

    func kitTimeFunction() {self.view.addSubview(colorView)colorView.frame = CGRect(x: 50, y: 50, width: 100, height: 100)colorView.backgroundColor = UIColor.yellow}override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {UIView.animate(withDuration: 1.0, delay: 0.0,options: .curveEaseInOut) {self.colorView.center = touches.first!.location(in: self.view)}}

效果如下:

可以看到它的效果和上面我们对图层设置慢进慢出效果是一样的。

关键帧动画和缓冲

关键帧动画的缓存相对于其它动画有一些特别,所以我们拎出来单独说它。就之前博客提到的颜色变化的动画来说,它有5个关键帧,我们在应用缓冲时,则需要设置4个缓冲函数,因为它所描述的是每一帧之间动画速度的函数。

接下来我们给使用关键帧改变图层颜色的动画每次改变都加上脉冲的效果,代码如下:

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {let keyFrameAnimation = CAKeyframeAnimation()keyFrameAnimation.keyPath = "backgroundColor"keyFrameAnimation.duration = 1.0// 五个颜色keyFrameAnimation.values = [UIColor.red.cgColor,UIColor.green.cgColor,UIColor.blue.cgColor,UIColor.yellow.cgColor,UIColor.orange.cgColor]// 五个时间点keyFrameAnimation.keyTimes = [0.0,0.2,0.4,0.6,0.8,1.0]// 缓冲keyFrameAnimation.timingFunctions = [CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeIn),CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeIn),CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeIn),CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeIn)]colorLayer.add(keyFrameAnimation, forKey: nil)}

效果如下:

结语

本篇博客我们介绍了图层动画和视图动画的缓冲函数,列举了一些常用的缓冲函数及其使用效果,最后我们讨论了关键帧动画缓存函数的设置方案。

不过对于动画的缓冲来说,这仅仅是一个开始,后面的博客我们将开始更加深入的探讨CAMediaTimingFunction是如何工作的,并且我们该如何自定义一个更适合自己动画的缓冲函数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3248132.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

TCP vs UDP:网络编程的双刃剑艺术

在浩瀚的网络编程世界里&#xff0c;TCP&#xff08;传输控制协议&#xff09;与UDP&#xff08;用户数据报协议&#xff09;如同两位性格迥异的剑客&#xff0c;各自以其独特的剑法与风格&#xff0c;在网络通信的舞台上独领风骚。今天&#xff0c;就让我们深入探索这两位网络…

【DevOps系列】DevOps简介及基础环境安装

作者&#xff1a;后端小肥肠 目录 1. 前言 2. DevOps&#xff08;详细介绍&#xff09; 3. Code阶段工具 3.1 Git安装 3.2 GitLab安装 4. Build阶段工具 5. Operate阶段工具 5.1 Docker安装 5.2 Docker-Compose安装 6. Integrate工具 6.1 Jenkins介绍 6.2 Jenkins安…

Axure中继器入门:打造你的动态原型

前言 中继器 是 Axure 中的一个高级功能&#xff0c;它能够在静态页面上模拟后台数据交互的操作&#xff0c;如增加、删除、修改和查询数据&#xff0c;尽管它不具备真实数据存储能力。 中继器就像是一个临时的数据库&#xff0c;为我们在设计原型时提供动态数据管理的体验&a…

Java二十三种设计模式-抽象工厂模式(3/23)

抽象工厂模式&#xff1a;复杂系统的灵活构建者 引言 在软件开发中&#xff0c;抽象工厂模式是一种提供接口以创建相关或依赖对象族的创建型设计模式。这种模式允许客户端使用一个共同的接口来创建不同的产品族&#xff0c;而无需指定具体类。 基础知识&#xff0c;java设计模…

Redis Cluster集群搭建只能正常启动一个怎么解决

Redis Cluster集群搭建只能正常启动一个怎么解决 建立redis集群时不小心就遇到了这问题 上图看 这两个都没有问题 接下来这个就出现问题啦 6380没有cluster集群 这个就是连不上 配置文件没错 看了几遍了 那该怎么办&#xff1f; 明明都一样的配置文件&#xff0c;为啥这…

成都亚恒丰创教育科技有限公司 【插画猴子:笔尖下的灵动世界】

在浩瀚的艺术海洋中&#xff0c;每一种创作形式都是人类情感与想象力的独特表达。而插画&#xff0c;作为这一广阔领域中的璀璨明珠&#xff0c;以其独特的视觉语言和丰富的叙事能力&#xff0c;构建了一个又一个令人遐想连篇的梦幻空间。成都亚恒丰创教育科技有限公司 在众多插…

解析DDD中的聚合对象

对象这个词对我们而言并不陌生。以最常见的面向对象为例&#xff0c;软件系统中的任何事物都被认为是一种对象。而针对如何设计和实现这些对象&#xff0c;也存在一批开发模式。例如&#xff0c;一种传统的做法是从数据的角度来规划对象的组织形式&#xff0c;先设计数据库模型…

甲骨文面试题【动态规划】力扣377.组合总和IV

给你一个由 不同 整数组成的数组 nums &#xff0c;和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。 题目数据保证答案符合 32 位整数范围。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3], target 4 输出&#xff1a;7 解释&#x…

QTableView仿Excel表头排序和筛选

一.效果 Excel的排序和筛选弹窗如下所示 功能非常强大。不仅支持内容排序和筛选,还支持颜色的排序和筛选,而且还支持设置多种过滤条件。本文只仿最常用的内容排序和内容单过滤条件的筛选,效果如下所示。 从效果图中可以看出,表头Section中的按钮有下列六种状态 enum Butt…

Redis 教程:从入门到入坑

目录 1. Redis 安装与启动1.1. 安装 Redis1.1.1. 在Linux上安装1.1.2. 在Windows上安装 1.2. 启动 Redis1.2.1. 在Linux上启动1.2.2. 在Windows上启动 1.3. 连接Redis1.3.1. 连接本地Redis1.3.2. 连接远程Redis1.3.2.1. 服务器开放端口1.3.2.2. 关闭防火墙1.3.2.3. 修改配置文件…

GESP CCF C++ 三级认证真题 2024年6月

第 1 题 小杨父母带他到某培训机构给他报名参加CCF组织的GESP认证考试的第1级&#xff0c;那他可以选择的认证语言有&#xff08;&#xff09;种。 A. 1 B. 2 C. 3 D. 4 第 2 题 下面流程图在yr输入2024时&#xff0c;可以判定yr代表闰年&#xff0c;并输出 2月是29天 &#x…

【整体介绍】HTML和JS编写多用户VR应用程序的框架

一、Networked-Aframe是什么&#xff1f; 简称NAF&#xff0c;底层基于Mozilla的AFrame框架&#xff0c;用HTML和JS编写多用户VR应用程序的框架。 二、特性 支持 WebRTC 和/或 WebSocket 连接。 语音聊天。音频流让您的用户在应用程序内交谈&#xff08;仅限 WebRTC&#xff…

AV1技术学习: Compound Prediction

一、双向 Compound Prediction AV1支持两个参考帧的预测通过多种复合模式线性组合。复合预测公式为 其中&#xff0c;权重m(x, y) is scaled by 64 以进行整数计算&#xff0c;R1(x, y)和R2(x, y)表示两个参考块中位于(x, y)的像素。P(x, y)将按比例缩小 1/64 以形成最终的预测…

Android安卓使用MQTT(JAVA)

一、app目录下添加 implementation org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0 1) 点击Sync Now更新依赖 2) AndroidManifest.xml文件添加网络权限 <uses-permission android:name"android.permission.INTERNET"/> 二、 使用 1) 创建MqttConn…

使用 ABBYY FineReader PDF 15 在创建或转换 PDF 时自动生成书签

使用 ABBYY 为 PDF 文件添加书签&#xff0c;可以帮助快速定位文档中的主要内容&#xff0c;也能更方便的梳理出一份文档大纲。 有很多 PDF 文件在创建时并没有编辑书签&#xff0c;这里介绍使用 ABBYY FineReader PDF 15&#xff08;Win 系统&#xff09;在 PDF 中自动添加书…

postMessageXss续2

原文地址如下:https://research.securitum.com/art-of-bug-bounty-a-way-from-js-file-analysis-to-xss/ 在19年我写了一篇文章&#xff0c;是基于postMessageXss漏洞的入门教学:https://www.cnblogs.com/piaomiaohongchen/p/14727871.html 这几天浏览mXss技术的时候&#xff…

第三周周三总结

1.给你一个 32 位的有符号整数 x &#xff0c;返回将 x 中的数字部分反转后的结果。 如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] &#xff0c;就返回 0。 假设环境不允许存储 64 位整数&#xff08;有符号或无符号&#xff09;。 示例 1&#xff1a; 输…

RuoYi-后端管理项目入门篇1

目录 前提准备 下载若依前后端 Gitee 地址 准备环境 后端数据库导入 1 克隆完成 若依后端管理后端 Gitte 地址 :若依/RuoYi-Vue 2.1 创建Data Source数据源 2.2 填写好对应的数据库User 和 Password 点击Apply 2.3 新建一个Schema 2.4 填写对应数据库名称 这边演示写的…

【I²C协议】STC89C51单片机IIC通信(代码+原理)

STC89C51单片机IIC通信 什么是IC协议特点构成 通信协议开始信号、结束信号、应答信号数据传输 代码示例 什么是IC协议 IIC,即IC&#xff0c;全称 Inter-Integrated Circuit&#xff0c;字面上的意思是集成电路之间&#xff0c;它其实是IC Bus简称&#xff0c;所以中文应该叫 集…

【Codeforces】Round 957 (Div. 3)_B. Angry Monk

作者&#xff1a;指针不指南吗 专栏&#xff1a;算法刷题 &#x1f43e;或许会很慢&#xff0c;但是不可以停下来&#x1f43e; 文章目录 题目题解try1代码正确题解贪心策略的解释为什么不是直接合并 总结 题目 题目链接 题解 try1代码 我的思路&#xff1a;单纯模拟 循环&a…