Canvas系列(12):动画高级
通过前面章节的学习,我们已经学会了直线和部分曲线运动,同时我们也学会了加速、减速、摩擦力等操作。那么动画还有什么需要深入研究下去的呢?当然有,那就是让动画更加平滑,更细滑。
缓动动画
在使用CSS3做变化的时候我们经常使用transition-timing-function
,其中最有名的两个值就是ease-in
和ease-out
,那canvas种怎么实现这中如丝般细滑的缓动动画呢?看完本章你就知道了。缓动的公式如下:
当前速度 = (最终位置 - 当前位置) * 缓动系数。 新的位置 = 当前位置 + 当前速度。
我们看一个简单的例子
//...
// 设置x的值放在最左边
var ballX = ballRadius;
var ballY = centerY;
// x的速度 具体是多少在update的时候计算
var vx;
// 缓动系数
var easing = 0.03;
// 最终位置 在最右边
var targetX = canvas.width - ballRadius;
// 更新小球
function updateBall(){
// 当前速度 = (最终位置 - 当前位置) * 缓动系数
vx = (targetX - ballX) * easing;
// 新的位置 = 当前位置 + 当前速度
ballX += vx;
}
//...
效果如下:
由上面公式中我们可以知道,缓动系数越大运动的越快。
带有角度的缓动动画
带有角度的缓动动画也是一样的,只要把y轴上的分量也计算进去就可以了。
//...
// 设置起始位置在左上角
var ballX = 0;
var ballY = 0;
// 速度 具体是多少在update的时候计算
var vx,vy;
// 缓动系数
var easing = 0.03;
// 最终位置 在右下角
var targetX = canvas.width - ballRadius;
var targetY = canvas.height - ballRadius;
// 更新小球
function updateBall(){
// 当前速度 = (最终位置 - 当前位置) * 缓动系数
vx = (targetX - ballX) * easing;
vy = (targetY - ballY) * easing;
// 新的位置 = 当前位置 + 当前速度
ballX += vx;
ballY += vy;
}
//...
效果如下:
由上可以,缓动动画只需要根据给定结束的位置就可以了,无需根据角度再进行计算,使用起来非常方便。通常由于缓动动画比摩擦力更细滑,所以减速后停来下的动画,基本上都用缓动动画。
缓动动画的其他使用场景
缓动动画计算的过程其实一个简单数学推到,本身并不是什么高深的东西(当然做出来的效果确实很好)。我们的思维不能定势到只能做物体移动的动画,只要有从状态A平滑变化到状态B的场景都可以使用缓动动画,就比如宽高的变化,颜色的变化,透明度的变化等等。我们这里给一个小球半径变化的例子:
//...
// 小球画在中间位置
var ballX = centerX;
var ballY = centerY;
// 缓动系数
var easing = 0.03;
// 最终位置 在右下角
var targetBallRadius = 70;
// 半径变化速度
var vRadius;
// 更新小球
function updateBall(){
// 当前速度 = (最终位置 - 当前位置) * 缓动系数
vRadius = (targetBallRadius - ballRadius) * easing;
// 新的位置 = 当前位置 + 当前速度
ballRadius += vRadius;
}
//...
效果如下:
弹性动画
缓动动画,当物体运动到终点的位置就会停下来;弹性动画,当物体运动到终点位置,会继续往前运动一下,然后反弹过来。那么怎么实现弹性动画呢?说出来你可能会不相信,缓动动画是速度使用缓动方程,而弹性动画是加速度使用缓动方程。也就是说:
当前加速度 = (最终位置 - 当前位置) * 弹性系数。 新的速度 = 当前速度 + 当前加速度。 新的位置 = 当前的位置 + 新的速度。
我们先来看一个例子:
//...
// 设置起始位置在左边
var ballX = ballRadius;
var ballY = centerY;
// 初始速度
var vx = 0;
var vy = 0;
// 加速度
var ax;
// 弹性动画系数
var spring = 0.01;
// 最终位置 在最右边
var targetX = centerX;
// 更新小球
function updateBall(){
// 当前加速度 = (最终位置 - 当前位置) * 弹性系数
ax = (targetX - ballX) * spring;
// 新的速度 = 当前速度 + 当前加速度
vx += ax;
// 新的位置 = 当前的位置 + 新的速度
ballX += vx;
}
//...
效果如下:
小球从左边,走到了中间,到中间的时候加速度是0,再往右一点,加速度是负数也就是减速,等减速到最右边的时候速度为0,然后向左边加速。通过上面公式我们发现第一个公式跟缓动公式是一样的,只是结果一个是加速度一个是速度,至于系数虽然这里叫的不一样,其实代表的含义差不多。
带有摩擦力的弹性动画
上面的弹性动画是理想状态下的,就是物理上所说的绝对光滑的情况下才会发生,而现实中往往是具有摩擦力的。摩擦力我们之前学过,弹性动画我们也学过,如果把两者结合起来就是带有摩擦力的弹性动画,公式如下:
当前加速度 = (最终位置 - 当前位置) * 弹性系数。 没有摩擦力的新的速度 = 当前速度 + 当前加速度。 带有摩擦力的新的速度 = 没有摩擦力的新的速度 * 摩擦系数。 新的位置 = 当前的位置 + 带有摩擦力的新的速度
//...
// 设置起始位置在左边
var ballX = ballRadius;
var ballY = centerY;
// 初始速度
var vx = 0;
var vy = 0;
// 加速度
var ax;
// 弹性动画系数
var spring = 0.01;
// 摩擦力系数
var friction = 0.98;
// 最终位置 在最右边
var targetX = centerX;
// 更新小球
function updateBall(){
// 当前加速度 = (最终位置 - 当前位置) * 弹性系数
ax = (targetX - ballX) * spring;
// 没有摩擦力的新的速度 = 当前速度 + 当前加速度
vx += ax;
// 带有摩擦力的新的速度 = 没有摩擦力的新的速度 * 摩擦系数
vx *= friction;
// 新的位置 = 当前的位置 + 带有摩擦力的新的速度
ballX += vx;
}
//...
效果如下:
建议你自己写一写代码,或者自己把代码下载下来运行一下,代码地址:https://github.com/KaiOrange/canvas-demo。
- Python之线程
- 3555: [Ctsc2014]企鹅QQ
- 【实战】RFID Hacking(1):看我如何突破门禁潜入FreeBuf大本营
- P2885 [USACO07NOV]电话线Telephone Wire
- 实战-Fluxion与wifi热点伪造、钓鱼、中间人攻击、wifi破解
- 【下载】PyTorch实现的神经网络翻译框架——机器翻译工具包 nmtpytorch
- P2605 [ZJOI2010]基站选址
- MYSQL之索引原理与慢查询优化
- MYSQL之视图、触发器、存储过程、函数、事物、数据库锁和数据库备份
- P1452 Beauty Contes
- Python基础(一)
- P1452 Beauty Contes(旋转卡壳版)
- python常见模块之os模块
- BZOJ 2127: happiness(最小割解决集合划分)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- php面试笔记-php基础知识-变量和引用变量
- 【STM32F429开发板用户手册】第34章 STM32F429的SPI总线应用之驱动DAC8501
- docker 安装mysql5.7
- php面试笔记(5)-php基础知识-自定义函数及内部函数考点
- AJAX的一个简单实例,跨域的解决,使用JQuery来进行ajax的调用
- ASP.NET Core 将文件夹内容输出为压缩包文件方法
- 如何阻止指定类型的SAP CRM附件被上传到服务器
- Docker 之NameSpace与Cgroup
- 微信网页扫码登录和公众号网页授权登录的比较
- 【TBase开源版测评】分布式数据库复制表关联查询
- v-decorator的取值与赋值
- fastjson导致spring security oauth2的token序列化错误
- 微信小程序webview,a锚点跳转,回退时一直保留在原页面
- SLURM使用教程
- MIME 类型大全,你值得收藏