likes
comments
collection
share

requestAnimationFrame的动画速度调整

作者站长头像
站长
· 阅读数 48

🔍requestAnimationFrame的默认帧数是根据浏览器的默认刷新率来确定的,目前大多数浏览器的刷新率为每秒60帧(60 frames per second,简称FPS),因此,如果你使用requestAnimationFrame来执行动画或进行其他涉及动态更新的操作时,它的默认帧数就是每秒60帧,也就是16ms刷新一帧。

下面我们看一段代码,实现一个移动方块,在不控制帧率的情况下,这个动画的持续时间我们是可以计算得出的。假设例子中浏览器的刷新率是60FPS,这个方块的总移动距离是400px(父元素宽500 - 子元素方块宽100,那么动画的持续时间:400 / 60 = 6.66秒 requestAnimationFrame的动画速度调整

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
        <style>
            body {
                box-sizing: border-box;
                display: flex;
                align-items: center;
                justify-content: center;
                height: 100vh;
                
            }
            .box {
                width: 500px;
                height: 100px;
                border: 2px solid #FFE9AE;
            }
            .box__item {
                height: 100%;
                width: 100px;
                background-image: linear-gradient(35deg, #FFB3B3, #FFDBA4);
            }
        </style>
    </head>
    <body>
        <div class="box">
            <div class="box__item"></div>
        </div>
    </body>
</html>
<script>
    const boxItem = document.querySelector(".box__item");
    const box = document.querySelector(".box");
    // 方块的移动目标距离: 父元素 - 子元素 - 父元素的左右边框宽度
    const targetPosition  = box.getBoundingClientRect().width - boxItem.getBoundingClientRect().width - 4;
    const initialPosition  = 0;
    let currentPosition = initialPosition
   
    function updataAnimate() {
        currentPosition += 1;
        boxItem.style.transform = `translateX(${currentPosition}px)`;
        if (currentPosition < targetPosition) {
            // 动画未完成,继续下一帧
            requestAnimationFrame(updataAnimate);
        }
    }
    requestAnimationFrame(updataAnimate)
</script>


下面我们控制这个动画的持续时间为2秒,将上面代码稍微改动一下

    const boxItem = document.querySelector(".box__item");
    const box = document.querySelector(".box");
    // 方块的移动目标距离: 父元素 - 子元素 - 父元素的左右边框宽度
    const targetPosition  = box.getBoundingClientRect().width - boxItem.getBoundingClientRect().width - 4;
    // 定义动画初始位置
    const initialPosition  = 0;
    // 设置2秒完成该动画
    const animationDuration = 2000;
    let startTime;
    function updataAnimate(timestamp) {
        // 记录动画开始时间
        if(!startTime) startTime = timestamp;
        // 计算动画的经过时间
        const elapsedTime = timestamp - startTime;
        // 计算动画的进度
        const progress = Math.min(elapsedTime / animationDuration, 1);
        // 获取当前位置
        const currentPosition = initialPosition + (targetPosition - initialPosition) * progress;
        // 更新动画
        boxItem.style.transform = `translateX(${currentPosition}px)`;
        if(progress < 1) requestAnimationFrame(updataAnimate)

    }
    requestAnimationFrame(updataAnimate)

requestAnimationFrame的动画速度调整

在上述代码中,我们利用startTimetimestamp计算出动画经过时间,然后计算出动画的进度,根据进度更新当前位置,如果进度值小于1则继续请求下一帧。

转载自:https://juejin.cn/post/7239249100335415357
评论
请登录