requestAnimationFrame 实验

43 阅读1分钟

requestAnimationFrame 实验

requestAnimationFrame MDN

window.requestAnimationFrame() 方法会告诉浏览器你希望执行一个动画。它要求浏览器在下一次重绘之前,调用用户提供的回调函数。

简而言之,这个方法会让动画表现得更丝滑。今天来做个小实验,看看它和 js, css 设置的动画的表现差异吧。

1. 获取帧率/屏幕刷新率

绘画离不开帧率,借助 performance API 可以大致得出当前屏幕刷新率。

function getRefreshRate(callback) {
    let frames = 0;
    let startTime = performance.now();

    function tick() {
        frames++;
        const currentTime = performance.now();
        const duration = currentTime - startTime;

        if (duration >= 1000) {
            const fps = Math.floor(frames / duration * 1000);
            callback(fps);
        } else {
            requestAnimationFrame(tick);
        }
    }

    requestAnimationFrame(tick);
}

检查

getRefreshRate((fps) => {
    console.log(`refresh rate: ${fps} Hz`);
})

结果(本人电脑):

my-fps.png

确实和本机设置里同值。

my-mac-fps.png

备注:这个计算帧率方法不绝对精确。

2. 偏移动画

设置三个元素,分别用 js-setInterval, js-requestAnimationFrame, css-animation 执行动画,对应代码:

const range = 500

function runA() {
    let tX = 1
    const timer = setInterval(() => {
        boxA.style.transform = `translateX(${tX}px)`;
        tX++;
        if(tX === range + 1) {
            clearInterval(timer)
        }
    }, 1000 / FPS_VALUE)
}

function runB() {
    let tX = 1

    const animate = () => {
        boxB.style.transform = `translateX(${tX}px)`;
        tX++;
        if(tX === range + 1) {
            return;
        }
        requestAnimationFrame(animate);
    }
    
    requestAnimationFrame(animate);
}

function runC() {
    const time = (range / FPS_VALUE) + 's'
    boxC.style.animation = `moveRight ${time} linear forwards`;
}

/*
// css
@keyframes moveRight {
    from {
        transform: translateX(0);
    }
    to {
        transform: translateX(500px);
    }
}
*/

3.效果

test.gif

忽略误差造成的移动速度差距,对比看出,boxA(setInterval 方法)比 boxB(requestAnimationFrame 方法),boxC(animation CSS)有些许卡顿,后两者表现相差无几。

可能 gif 表现不明显--特别是在网站上看,下面有完整代码,拷贝到本地用浏览器打开即可。

完整代码 Github

See u! 感谢阅读