码迷,mamicode.com
首页 > 其他好文 > 详细

requestAnimationFrame 简单应用

时间:2020-09-17 17:36:26      阅读:19      评论:0      收藏:0      [点我收藏+]

标签:space   mamicode   title   star   spl   margin   add   告诉   height   

window.requestAnimationFrame 简单应用

这是一个实验中的功能。

00 需求背景

在实现一个动画的时候,一般情况下会使用setTimeout方法。
但是 setTimeout方法容易出现卡顿、抖动的现象,原因是:

  • 01 setTimeout任务被放入异步队列,只有当主线程任务执行完后才会执行队列中的任务,因此实际执行时间总是比设定时间要晚;
  • 02 setTimeout的固定时间间隔不一定与屏幕刷新时间相同,会引起丢帧。

01 requestAnimationFrame

该方法告诉浏览器需要执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。
该方法需要传递一个回调函数作为参数。

回调函数的执行时机由系统决定,每次刷新屏幕的间隔执行一次,因此不会出现丢帧和卡顿的现象。

如果想在浏览器下次重绘之前继续更新下一帧动画,那么回调函数自身必须再次调用 requestAnimationFrame

语法

window.requestAnimationFrame(callback);

参数

callback -- 下一次重绘之前更新动画帧所调用的函数。

返回值

返回一个long整数,标识请求 ID, 是回调列表种的唯一标识。可以传递这个值给 window.cancelAnimationFrame()方法以停止动画。

02 cancelAnimationFrame

该方法用于停止指定的requestAnimationFrame

语法

window.cancelAnimationFrame(requestAnimationFrameID);

参数

requestAnimationFrameID -- requestAnimationFrame返回的请求标识 ID

03 requestAnimationFrame 的优点

  • 01 requestAnimationFrame会把每一帧种的所有 DOM 操作集中起来,再一次重绘或回流中完成,重绘或回流的时间间隔就是浏览器的刷新频率。
  • 02 对隐藏不可见的元素 requestAnimationFrame将不会进行重绘或回流,这就意味着可以减少 cpu, gpu 的使用。

04 应用实例

暂时没有找到合适的截图工具,就先放一张静态图片:
技术图片

JS 核心代码

let startBtn = document.querySelector(‘.start‘);
let endBtn = document.querySelector(‘.end‘);
let moveBox = document.querySelector(‘.move-box‘);

// 请求帧的标识
let handle;

let startPos = 0;
let endPos = document.body.clientWidth - moveBox.clientWidth;
let stepLength = endPos / 60 / 4;

startBtn.addEventListener(‘click‘, function (){
    // 执行动画并获取标识 ID
    handle = window.requestAnimationFrame(moveFunc);
});

endBtn.addEventListener(‘click‘, function (){
    // 取消动画
    window.cancelAnimationFrame(handle);
});

function moveFunc() {
    startPos += stepLength;
    moveBox.style[‘left‘] = `${startPos}px`;
    if (startPos <= endPos) {
        // 注意更新 handle
        handle = window.requestAnimationFrame(moveFunc);
    }
}

完整代码

<!DOCTYPE html>
<html lang="zh-CN">

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

    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
    </style>
</head>

<body>
    <style>
        .move-box {
            position: relative;
            left: 0;
            width: 100px;
            height: 100px;
            background-color: purple;
        }

        .btn-container {
            margin: 10px auto;
            width: 220px;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .start, .end {
            width: 100px;
            height: 30px;
            color: #fff;
            font-size: 20px;
            font-weight: 650;
            text-align: center;
            line-height: 30px;
            cursor: pointer;
            background-color: orange;
        }
    </style>

    <h3 style="color: red; text-align: center">-- requestAnimationFrame --</h3>
    <div class="btn-container">
        <div class="start">START</div>
        <div class="end">END</div>
    </div>
    <div class="move-box"></div>

    <script>
        let startBtn = document.querySelector(‘.start‘);
        let endBtn = document.querySelector(‘.end‘);
        let moveBox = document.querySelector(‘.move-box‘);

        // 请求帧的标识
        let handle;

        let startPos = 0;
        let endPos = document.body.clientWidth - moveBox.clientWidth;
        let stepLength = endPos / 60 / 4;
        
        startBtn.addEventListener(‘click‘, function (){
            // 执行动画并获取标识 ID
            handle = window.requestAnimationFrame(moveFunc);
        });

        endBtn.addEventListener(‘click‘, function (){
            // 取消动画
            window.cancelAnimationFrame(handle);
        });

        function moveFunc() {
            startPos += stepLength;
            moveBox.style[‘left‘] = `${startPos}px`;
            if (startPos <= endPos) {
                // 注意更新 handle
                handle = window.requestAnimationFrame(moveFunc);
            }
        }
    </script>
</body>

</html>

requestAnimationFrame 简单应用

标签:space   mamicode   title   star   spl   margin   add   告诉   height   

原文地址:https://www.cnblogs.com/mrdragon/p/13628370.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!