JS原生animate动画函数之复合动画与缓动动画

位置: 首页 > 前端三套件
[发布: 2024.6.7  作者: 马黑  阅读: 58]

这里的复合动画指动画的混合运行,每一帧执行两个或以上的动画,比如元素在旋转的同时还变换色相。这在CSS关键帧动画中非常简单,在动画帧描述中用分号隔开不同的动画描述即可。而在JS原生animate动画中实现复合动画,我们需要在 keyframes 参数即动画参数上做文章:keyframes 参数是动画各帧的描述对象,它可以是数组形式的对象集合,试看如下代码:

const ani = [     {transform: 'rotate(0)', filter: 'hue-rotate(0)'},     {transform: 'rotate(360deg)', filter: 'hue-rotate(240deg)'} ];

以上,我们定义了一个名为 ani 的动画数组,数组的子项是两个对象,每一个对象都有两个键值对,健名分别是 transform 和 filter,分别用以描述转换动画和滤镜动画。首尾帧规定了旋转动画从 0 到 360 度、色相从 0 到 240 度进行旋转、变色。如果需要,每一帧还可以添加别的动画,都是用键值对的方式表达,两个键值对之间用小角逗号隔开即可,最末一个键值对后面有没有逗号都可以,从美观的角度考虑应该不要。

我们给animate函数加上 options 参数,动画就可以立马运行。下面的代码,在《初识JS原生animate动画函数》的基础上略作改动,图片除了旋转还改变色相,动画可控,可以将代码复制到pencil code运行以查看效果:

<img id="h7" alt="" width="200" src="https://638183.freep.cn/638183/web/svg/sunfl-2.svg" /> <script> // ani数组 :keyframes参数,旋转、变色动画描述(首帧可以省略) const ani = [ {transform: 'rotate(0)', filter: 'hue-rotate(0)'}, {transform: 'rotate(360deg)', filter: 'hue-rotate(240deg)'} ]; // aniAttr对象 :options参数,动画属性值列表 const aniAttr = { duration: 8000, iterations: Infinity, }; // 运行并获得动画操作入口 h7Ani const h7Ani = h7.animate(ani, aniAttr); //图片单击事件 : 暂停或继续动画 h7.onclick = () => h7Ani.playState === 'running' ? h7Ani.pause() : h7Ani.play(); </script>

复合动画的关键是animate函数参数1 keyframes 的表达,其方式是用数组来组织各帧动画,每一帧的动画用JS对象来表示,对象里头每一个键值对描述一种动画在该帧的状态,两个键值对间用小角逗号隔开。

缓动动画则是高级动画绕不开的技术话题。所谓缓动就是缓冲,指的是运动的物体由于受到阻力或加速度的影响,在运动过程中速度不断衰减或不断提升。加速的动画称为缓入动画,减速的动画叫做缓出动画。本文示例演示缓出动画,旋转的图片持续减速,以至最终停下——不过由于使用了 Infinity 动画属性,理论上旋转的图片是永远停不下来的,感兴趣的朋友请查阅芝诺悖论

animate动画对象有一个 playbackRate 属性,可读写,用于返回或设置动画的播放速率。我们可以借助定时器 setInterval 在设定时间范围内持续改变其值,例如乘以0.9,动画的播放速率就会不断地慢下来。假设我们的上述动画是环保而高端的9块9包邮的可充电设备,现在我们给它加入耗电机制,电力的减退导致它的运行速度不断减缓,直到我们给它充满电再让它满血回归:

 1

以下是上述示例的完整代码:

<p><img id="h7" alt="" width="200" src="https://638183.freep.cn/638183/web/svg/sunfl-2.svg" /></p> <p><button id="charge" type="button" value="btn">电量</button>  <output id="rateMsg"></output></p>   <script>   const ani = [     {transform: 'rotate(0)', filter: 'hue-rotate(0)'},     {transform: 'rotate(1800deg)', filter: 'hue-rotate(240deg)'} ];   const aniAttr = {     duration: 10000,     iterations: Infinity, };   const h7Ani = h7.animate(ani, aniAttr);   setInterval(() => {     let val = Math.round(h7Ani.playbackRate * 100) / 100;     charge.innerHTML = val <= 0.05 ? '<span class="tRed">充电</span>' : '电量';     charge.value = val <= 0.05 ? '0' : '1';     rateMsg.value = val;     h7Ani.playbackRate *= 0.9; },1000);   charge.onclick = () => {     if(charge.value === '0') h7Ani.playbackRate = 1; };   </script>

重点在 setInterval 定时器,它每隔 1000 毫秒令 h7Ani 动画的播放速率变为上一秒速率的 90%,从而达到动画速率持续下降也就是缓动的目的,代码在第 23 行。定时器还顺带改变充电按钮的文本,并实时显示当前电量。关于电量的计算,为了避免科学计数的出现影响按钮操作,我们以四舍五入的方法只取浮点数小数点后两位数,所以电量最终会变为 0,符合现实生活规律,芝诺悖论也因此不攻自破。

充电按钮的点击事件,负责给电器充电,但只有在电量不足 5% 时才能充电。这是标准的超级快充,点击一下就能充满电,处于充电行业全宇宙遥遥领先的地位。

前一篇: 初识JS原生animate动画函数
下一篇: JS原生animate动画函数之动画联动

发表评论:

  
 

评论列表 [1条]

#1 | 悄然 于 2024-6-7 08:09 发布: 被这个充电功能惊艳到了。。从未见过的实现方法。。居然还可以这么整。。

Copyright © 2023 All Right Reserved 马黑PHP文章管理整站系统v1.8
联系我们: gxblk@163.com