美文网首页web前端
requestAnimationFrame

requestAnimationFrame

作者: 姜治宇 | 来源:发表于2021-02-04 11:04 被阅读0次

setTimeout和setInterval

我们在用js实现动画时,经常会用到setTimeout和setInterval函数,但实际上它们都不精确。因为setTimeout和setInterval函数只是将任务放进异步队列中,只有当主线程上的任务执行完以后,才会去检查该队列里的任务是否需要开始执行,因此setTimeout和setInterval的实际执行时间,一般要比其设定的时间晚一些。

requestAnimationFrame

requestAnimationFrame的优势是:

CPU节能

使用setTimeout实现的动画,当页面被隐藏或最小化时,setTimeout 仍然在后台执行动画任务,由于此时页面处于不可见或不可用状态,刷新动画是没有意义的,完全是浪费CPU资源。而requestAnimationFrame则完全不同,当页面处理未激活的状态下,该页面的屏幕刷新任务也会被系统暂停,因此跟着系统步伐走的requestAnimationFrame也会停止渲染,当页面被激活时,动画就从上次停留的地方继续执行,有效节省了CPU开销。

函数节流

在高频率事件(resize,scroll等)中,为了防止在一个刷新间隔内发生多次函数执行,使用requestAnimationFrame可保证每个刷新间隔内,函数只被执行一次,这样既能保证流畅性,也能更好的节省函数执行的开销。一个刷新间隔内函数执行多次时没有意义的,因为显示器每16.7ms刷新一次,多次绘制并不会在屏幕上体现出来。

实例

requestAnimationFrame的用法比较简单,跟setTimeout基本一样。

1、无卡滞渲染十万条数据
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <ul>

    </ul>
</body>
</html>
<script>
    const total = 100000;//数据条数
    const once = 20;//一次插入条数
    const loopNum = Math.ceil(total/once);//循环数
    let countRender = 0;//渲染次数
    const ul = document.querySelector('ul');
    
    function addItem(){

        const fragment = document.createDocumentFragment();
        for(let i=0;i<once;i++){
            const li = document.createElement('li');
            li.innerHTML =`第${countRender}批数据:::id==>${i}`;
            fragment.appendChild(li);//这里不消耗dom性能
        }
        ul.appendChild(fragment);//20次添加,其实只消耗1次dom性能
        countRender++;
        console.log(countRender);
       
    } 

    var timer = window.requestAnimationFrame(function fn(){
        if(countRender < loopNum) {
            addItem();
            timer = window.requestAnimationFrame(fn); // 递归
        }else{
            cancelAnimationFrame(timer);
        } 
        
    });
</script>
2、进度条效果
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="myDiv" style="background-color: lightblue;width: 0;height: 20px;line-height: 20px;">0%</div>
    <button id="btn">run</button>
    <script>
        var timer;
        btn.onclick = function () {
            myDiv.style.width = '0';
            cancelAnimationFrame(timer);
            timer = requestAnimationFrame(function fn() {
                if (parseInt(myDiv.style.width) < 500) {
                    myDiv.style.width = parseInt(myDiv.style.width) + 5 + 'px';
                    myDiv.innerHTML = parseInt(myDiv.style.width) / 5 + '%';
                    timer = requestAnimationFrame(fn);
                } else {
                    cancelAnimationFrame(timer);
                }
            });
        }
    </script>

</body>

</html>

参考文章:
https://blog.csdn.net/vhwfr2u02q/article/details/79492303

相关文章

网友评论

    本文标题:requestAnimationFrame

    本文链接:https://www.haomeiwen.com/subject/nvfbtltx.html