requestAnimationFrame理解及简单应用

window.requestAnimationFrame(callback),接受一个函数作为参数,在浏览器下次重绘前执行,大约是17毫秒(1000ms的60分之一,60HZ)左右执行一次(不同显示器刷新频率不同,75HZ,120HZ等刷新的间隔更短)。

rAF主要是做动画的,好处是不卡顿,动画也可以用setTimeout函数模拟,但是会卡顿。

为什么定时器会卡,而requestAnimationFrame不会卡

  • 定时器的回调函数,会受到js的事件队列宏任务、微任务影响,可能设定的是17毫秒执行一次,但是实际上这次是17毫秒、下次21毫秒、再下次13毫秒执行,所以并不是严格的卡住了这个60HZ的时间,会给人卡顿的感觉

为何requestAnimationFrame不会卡

  • rAF能够做到,精准严格的卡住显示器刷新的时间,比如普通显示器60HZ它会自动对应17ms执行一次,比如高级显示器120HZ,它会自动对应9ms执行一次。

rAF只会执行一次,想要多次执行,需要递归调用。

  • rAF也有返回值,返回值是一个整数,主要是定时器的身份证标识,可以使用 window.cancelAnimationFrame(返回值)来取消回调函数执行,相当于定时器中的clearTimeout()。

应用-跳转顶部动画

 <div class="test"></div>
 <button id="btn-jump">跳转顶部</button>
    <script>
        var jumpBtn = document.getElementById("btn-jump")
        var jumpFn1 = null
        var jumpFn = () => {
            var scrollTop = document.documentElement.scrollTop || document.body.scrollTop
            if(scrollTop > 0) {
                jumpFn1 = window.requestAnimationFrame(jumpFn)
                window.scrollTo(0, scrollTop - scrollTop / 10) //跳转y坐标根据需求效果更改
            }
        }
        jumpBtn.addEventListener("click",jumpFn)
    </script>

应用-进度条

<style>
      .c-box{
          margin: 10px auto;
          width: 400px;
          height: 5px;
          border-radius: 5px;
          background-color: #ccc;
      }
      .c-pr {
          width: 0;
          height: 100%;
          background: #00a1ff;
          border-radius: 5px;
      }
   </style>
    <div class="c-box">
        <div class="c-pr" id="c-pr"></div>
    </div>
    <p class="c-txt" id="c-txt">进度:0</p>
    <button id="c-start">开始</button>
    <script>
        var cBtn = document.getElementById("c-start")
        var cPr = document.getElementById("c-pr")
        var cTxt = document.getElementById("c-txt")
        var cWidth = 0
        var cFn = null
        var goFn = () => {
            if(cWidth <= 398) {
                cWidth += 2
                cPr.style.width = cWidth + 'px'
                cFn = window.requestAnimationFrame(goFn)
                cTxt.innerText = '进度:' + ((cWidth / 400) * 100).toFixed(2) + '%'
                console.log(111); 
            } else {
                window.cancelAnimationFrame(cFn)
                cFn = null
                cWidth = 0
            }
        }
        var toggleFn = () => {
            if(cFn) {
                window.cancelAnimationFrame(cFn)
                cFn = null
            } else {
                goFn()
            }
        }
        cBtn.addEventListener("click",toggleFn)
    </script>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容