本文最后更新于:2024-11-02T17:08:04+08:00
目录
前言
settimeout/setinterval
requestAnimationFrame
基本用法
时间戳参数
帧数与时间戳计算
自动暂停
JS中的贝塞尔曲线
概念
公式
二次贝塞尔
三次贝塞尔
N次贝塞尔
贝塞尔曲线+动画
动画类
在动画中使用贝塞尔
总结
相关代码:
贝塞尔曲线相关网站:
参考文章:
前言
上篇文章我们详细的讲述了CSS中的原生动画技术,了解了过渡与动画属性。那么本文将与大家分享原生JS中的动画方案,有兴趣的同学请接着往下看
JS实现动画的形式有定时器,动画帧以及动画API技术
settimeout/setinterval
早期的JS中动画帧和动画API的概念尚不存在,开发者通常使用定时器生成对应动画
我使用上面的代码实现了一个简单的匀速运动,其中按钮一控制运动和暂停,按钮二控制运动的方向,其中speed用于控制速度,frame控制帧数,下面是动画效果
requestAnimationFrame
requestAnimationFrame早在2011就由W3C提出了,它是一种用于在浏览器中执行动画效果的方法,我们在前文讲述事件循环时提到过,它属于宏任务的一种,但是在settimeout之前执行,在执行完微任务后,会执行requestAnimationFrame调度动画帧,然后浏览器会进行重绘和重排。相对于定时器,这样做可以使requestAnimationFrame中的dom操作得到优化,提高性能
基本用法
我们使用动画帧的方式来实现一下上面的效果
时间戳参数
requestAnimationFrame的钩子函数中会回传一个参数,这个参数是当前页面运行的时间戳,它是相对于页面加载的某个参考点来计算的,因此第一次的值会大于0。
这个时间戳是什么?
浏览器提供了一个性能监控的api:performance,其中performance.now()函数会返回当前时间戳,这个时间戳是以页面打开时间(performance.timing.navigationStart)为起点的
我们将浏览器的生命周期看成是一条时间轴,里面有许多时间节点,当执行requestAnimationFrame时相当于进入了时间轴的某个时间点,每一段时间会调用一个回调函数,当然当运行cancelAnimationFrame时相当于跳出了这个时间轴,当下次再进入时间轴时接着调用回调,流程可以参考下图
运行下面的代码可以打印出动画帧的时间戳
帧数与时间戳计算
基于上面的知识点和代码,我们可以利用performance和动画帧实现一个动画计时和帧数计算,请思考下面的代码
效果如下
自动暂停
基于上面的知识点,我们还可以将其应用到实际场景中,如果有一个动画需要限制其运行时间,比如一秒(限制时间可以更好的使用贝塞尔曲线),那么我们可以参考下面的代码
效果如下:
我们在每一次点击开始动画都会将firstStamp重置,以保证动画的周期始终是一秒
JS中的贝塞尔曲线
上述的动画使用的运动方式都是匀速运动,为了让动画更平滑,提升视觉观感,我们同样可以在JS中使用贝塞尔曲线
概念
在高中和大学,我们可能接触到了导数,也大致了解过速度与加速度的关系,贝塞尔曲线的变化是线性的,为了保证动画的可预测和可控性,贝塞尔曲线长度通常是有限的
下面两张图分别是使用德卡斯特里奥算法生成的二次和三次贝塞尔曲线的动画,动画来源于贝塞尔曲线
公式
下面是贝塞尔曲线的JS实现方式,我们假设起始点坐标是0,0,结束坐标是1,1。
二次贝塞尔
p0和p2坐标是(0,0)和(1,1)
三次贝塞尔
与二次类似,假设初始点和末尾点固定为(0,0)和(1,1)
N次贝塞尔
通过上述的推导,我们可以总结出一个N次贝塞尔的函数
贝塞尔曲线+动画
动画类
将贝塞尔引入JS之前,我们先基于上面的动画帧实现一个动画类便于后续的使用
在动画中使用贝塞尔
接着,我们将贝塞尔的函数代入到动画帧中,使用我们上面说到的贝塞尔公式和动画帧可以实现JS动画缓动的效果
上述代码的效果如下
CSS的效果如下
总结
本文主要介绍了两种JS实现动画的方式,分别是使用定时器和动画帧,其中动画帧的使用效果要优于定时器,它是在重绘和重排之前运行,节省了性能;接着我们详细了解了贝塞尔曲线的实现以及应用,在动画帧中使用了贝塞尔曲线,用于实现缓动效果
以上就是文章全部内容了,谢谢你看到最后,希望文章对你有帮助,如果觉得文章不错的话,还望三连支持一下博主,感谢!
相关代码:
myCode: 基于js的一些小案例或者项目 - Gitee.com
贝塞尔曲线相关网站:
cubic-bezier.com
贝塞尔曲线在线绘制🚀
参考文章:
贝塞尔曲线
Bézier_curve