请求动画帧 requestAnimationFrame

效果展示

函数解释

MDN描述:window.requestAnimationFrame() 告诉浏览器你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行

CSDN相关文档CSDN相关文档

创建和销毁

JavaScript
function animate() {
  // 执行动画逻辑
  timer = requestAnimationFrame(animate);
}

// 启动动画
let timer = requestAnimationFrame(animate);

//取消动画
 cancelAnimationFrame(timer);

requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,
并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率。充分利用了显示器的刷新机制,比较节省系统资源
(显示器有固定的刷新频率(60Hz或75Hz),也就是说,每秒最多只能重绘60次或75次)

requestAnimationFrame是一个全局函数。
调用requestAnimationFrame后,它会要求浏览器根据自己的频率进行一次重绘,
它会接收一个回调函数作为参数,在浏览器即将开始重绘时,会调用这个函数,
并会给这个函数传入调用回调函数时的时间作为参数。之后会反复不断地调用requestAnimationFrame,
以达到动画效果;

节省了CPU、GPU和电力,当页面处理未激活的状态下,该页面的屏幕刷新任务也会被系统暂停,因此跟着系统步伐走的requestAnimationFrame也会停止渲染,当页面被激活时,动画就从上次停留的地方继续执行,有效节省了CPU、GPU和电力开销

上方效果的完整代码

HTML
    <style>
        .SM_loadingBox {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 5vh;
        }

        .SM_loadingBox .item {
            width: 20px;
            height: 20px;
            background-color: rgb(24, 24, 24);
            margin: 5px;
            border-radius: 50%;
            transition: all .5s;
        }

        .item.on {
            animation-name: on;
            animation-duration: .5s;
            animation-fill-mode: forwards;
            background-color: burlywood;
        }

        @keyframes on {
            0% {
                width: 20px;
                height: 20px;
            }

            50% {
                width: 25px;
                height: 35px;
            }

            100% {
                width: 20px;
                height: 20px;
            }
        }
    </style>
</head>

    <div class="SM_loadingBox">
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
    </div>

    <script>
        const loading = document.querySelectorAll('.SM_loadingBox .item')
        let index = 0
        let timer = null

        function changeLoadingMov(timestamp) {
            if (!changeLoadingMov.startTime) {
                changeLoadingMov.startTime = timestamp;
            }
            const progress = timestamp - changeLoadingMov.startTime;
            if (progress > 500) {
                loading[index % loading.length].classList.add('on');
                index++;
                changeLoadingMov.startTime = timestamp;
            }
            if (index < loading.length) {
                timer = requestAnimationFrame(changeLoadingMov);
            } else {
                setTimeout(() => {
                    loading.forEach(item => item.classList.remove('on'));
                    cancelAnimationFrame(timer)
                    setTimeout(() => {
                        index = 0;
                        timer = requestAnimationFrame(changeLoadingMov);
                    }, 500);
                }, 500);
            }
        }

        timer = requestAnimationFrame(changeLoadingMov);
    </script>

请求动画帧 requestAnimationFrame》有一个想法

发表回复