缓冲运动和匀速运动的区别
匀速运动:速度一直不变的运动
缓冲运动:速度逐渐加快或者减慢的运动
缓冲运动的速度处于不断的变化中,和匀速运动不同的是,缓冲运动一般不设置初始速度,而是在运动函数内部进行计算。
缓冲运动公式
缓冲运动是速度逐渐变化的运动,速度公式为:(目标点 - 当前位置)/ 缩放系数
缓冲运动的停止条件:当前位置 = 目标点
修改 animate 函数:
function animate(ele = null,config = {
attrs:{},
scale:10,
}){
// 清除定时器
clearInterval(ele.timer);
const attrs = config.attrs;
const scale = config.scale;
return new Promise((resolve)=>{
ele.timer = setInterval(()=>{
let flag = true;
for(const attr in attrs){
// 设置目标距离
let target = Number.parseInt(attrs[attr]);
// 获取当前的样式
let currentStyle = (attr === "opacity")?(Number.parseInt(Number.parseFloat(getCurrentStyle(ele,attr))*100)):Number.parseInt(getCurrentStyle(ele,attr));
// 如果改变的样式是 opacity,target乘以100
if(attr === "opacity"){
target = Number.parseInt(Number.parseFloat(attrs[attr])*100);
}
// 获取速度
let speed = (target - currentStyle) / scale
speed = (speed > 0) ? Math.ceil(speed):Math.floor(speed);
// 根据运动是否完成来设定 flag
if(currentStyle !== target){
flag = false;
}
// 运动到目标点后清除定时器
if(currentStyle === target){
ele.style[attr] = (attr === "opacity")? target / 100 : target + "px";
}else{
// 根据当前样式动态改变物体的样式
ele.style[attr] = (attr === "opacity")?( currentStyle + speed)/100:(currentStyle + speed) + "px";
currentStyle += speed;
}
}
if(flag){
clearInterval(ele.timer);
resolve();
}
},30);
});
}
调用运动函数:
const ele = document.getElementById("inner");
const par = document.getElementById("par");
async function start(){
await animate(ele,{
attrs:{
left:"500px",
},
scale:10,
});
await animate(ele,{
attrs:{
left:0,
},
scale:5,
});
}
查看效果:
关于速度计算
现在解释下上面的速度计算方式:
let speed = (target - currentStyle) / scale
speed = (speed > 0) ? Math.ceil(speed):Math.floor(speed);
由于我们给的 scale 并不总是让 speed 的计算结果为整数,很可能出现浮点数的情况,因此需要对 speed 浮点数进行处理。在处理时又分为两种情况:
- speed > 0
- speed < 0
当 speed >0 时,speed 无限接近于 +0,以缩放系数为 10 进行举例:
运动次数 | 速度 | 位置 | 目标位置 |
---|---|---|---|
1 | 50 | 50 | 500 |
2 | 45 | 95 | 500 |
3 | 40.5 | 135.5 | 500 |
... | ... | ... | 500 |
43 | 1 | 491 | 500 |
44 | 0.9 | 491.9 | 500 |
45 | 0.9 | 491.9 | 500 |
... | ... | 491.9 | 500 |
在某个时候,速度会成为小数,于是当前位置也是小数,由于像素不可能有小数值,于是当前位置后的小数值会被抛弃,看起来小滑块停止到目标点之前了,而定时器仍然在运动(当前位置不等于目标位置),如图所示:
因此我们将速度向上取整,当速度小于 1 时,取整后速度为 1,最终的速度为 1,就能保证小滑块一像素一像素的移动到目标点,然后停止定时器。
当 speed < 0 时,分析方式和上面一样。这里便不再赘述,结论是当速度小于 0 时,对速度进行向下取整,最终速度为 -1。
多值缓冲运动
由于缓冲运动是基于前面的运动框架搭建的,因此也是支持多值运动的,下面罗列出一个栗子:
const ele = document.getElementById("inner");
async function start(){
await animate(ele,{
attrs:{
left:"500px",
width:"50px",
height:"50px",
fontSize:"10px",
lineHeight:"50px",
opacity:1,
},
scale:10,
});
}
效果如图:
总结
本文介绍了缓冲运动,下面简单总结下二者的差距:
| | 缓冲运动 | 匀速运动 |
| :--------: | :-----: | :----: | :----: |
|运动形式 | 速度越来越慢 | 速度不变 |
|停止条件 | 当前位置和目标点重合 | 当前位置和目标点差值的绝对值小于速度值 |
|速度 | 需要进行取整操作 | 速度不变 |
|最终速度 | 1 或 -1 | 速度不变 |
从视觉效果来看,缓冲运动比匀速运动更为炫酷一些,也是常用的运动方式。后序的文章中,我们还会介绍另外两种运动形式:弹性运动和碰撞运动。
完。