JavaScript 运动 03 —— 缓冲运动

缓冲运动和匀速运动的区别

匀速运动:速度一直不变的运动
缓冲运动:速度逐渐加快或者减慢的运动
缓冲运动的速度处于不断的变化中,和匀速运动不同的是,缓冲运动一般不设置初始速度,而是在运动函数内部进行计算。

缓冲运动公式

缓冲运动是速度逐渐变化的运动,速度公式为:(目标点 - 当前位置)/ 缩放系数
缓冲运动的停止条件:当前位置 = 目标点
修改 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,
    });
}

查看效果:

JavaScript 运动 03 —— 缓冲运动_第1张图片
缓冲运动.gif

关于速度计算

现在解释下上面的速度计算方式:

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

在某个时候,速度会成为小数,于是当前位置也是小数,由于像素不可能有小数值,于是当前位置后的小数值会被抛弃,看起来小滑块停止到目标点之前了,而定时器仍然在运动(当前位置不等于目标位置),如图所示:

JavaScript 运动 03 —— 缓冲运动_第2张图片
缓冲运动速度-1.gif

因此我们将速度向上取整,当速度小于 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,
    });
}

效果如图:

JavaScript 运动 03 —— 缓冲运动_第3张图片
多值缓冲运动.gif

总结

本文介绍了缓冲运动,下面简单总结下二者的差距:

| | 缓冲运动 | 匀速运动 |
| :--------: | :-----: | :----: | :----: |
|运动形式 | 速度越来越慢 | 速度不变 |
|停止条件 | 当前位置和目标点重合 | 当前位置和目标点差值的绝对值小于速度值 |
|速度 | 需要进行取整操作 | 速度不变 |
|最终速度 | 1 或 -1 | 速度不变 |

从视觉效果来看,缓冲运动比匀速运动更为炫酷一些,也是常用的运动方式。后序的文章中,我们还会介绍另外两种运动形式:弹性运动和碰撞运动。

完。

你可能感兴趣的:(JavaScript 运动 03 —— 缓冲运动)