定义

requestAnimationFrame是一个用于动画效果的 API,它使用浏览器的刷新率来执行回调函数,通常每秒钟执行60次(如果刷新率为120hz,则每秒执行120次),用法与setTimeout、setInterval很相似,但不需要设置时间间隔。

特点

  1. 动画效果更流畅:requestAnimationFrame的执行跟着系统的绘制频率走。它能保证回调函数在屏幕每一次的绘制间隔中只被执行一次,这样就不会引起丢帧现象,也不会导致动画出现卡顿的问题。(如果系统绘制率是 60Hz,那么回调函数就会16.7ms再 被执行一次,如果绘制频率是75Hz,那么这个间隔时间就变成了 1000/75=13.3ms)
  2. 更少的CPU、GPU和内存使用量:在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,且requestAnimationFrame是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销

与setTimeout、setInterval对比

在这里插入图片描述

执行时机

setTimeout和setInterval的回调函数在指定的延迟之后执行,不考虑浏览器的渲染过程。requestAnimationFrame的回调函数会在浏览器下一次重绘之前执行,确保动画在浏览器的重绘间隔中执行,从而实现更流畅的动画效果。

性能优化

requestAnimationFrame在浏览器的重绘间隔内执行,可以最大程度上利用浏览器的优化,避免不必要的重绘,提高性能。setTimeout和setInterval则可能会在浏览器不需要重绘的时候执行,导致性能损耗。

暂停与恢复

使用requestAnimationFrame可以更容易地控制动画的暂停和恢复,因为可以通过控制是否调用requestAnimationFrame来实现。而setTimeout和setInterval需要额外的逻辑来实现暂停和恢复。

总结

requestAnimationFrame更适合用于实现动画效果,能够提供更好的性能和流畅度,而setTimeOut和setInterval则用于实现定时任务

代码示例

<body>
    <div id="frameDiv">requestAnimationFrame</div>
    <div id="setTimeoutDiv">setTimeout</div>
    <div id="setIntervalDiv">setInterval</div>

    <script>
        let curFrameWidth = 0
        let curTimeoutWidth = 0
        let curIntervalWidth = 0
        let animateFrame = undefined
        let timeout = undefined
        let interval = undefined
        const maxWidth = 1024
        const $frameDiv = $('#frameDiv')
        const $setTimeoutDiv = $('#setTimeoutDiv')
        const $setIntervalDiv = $('#setIntervalDiv')

        // 使用 requestAnimationFrame()
        function FrameAnimate(){
            curFrameWidth = curFrameWidth + 3
            $frameDiv.css('width', curFrameWidth)
            if(curFrameWidth < maxWidth){
                animateFrame = window.requestAnimationFrame(FrameAnimate) // 时间不用自己控制
            }
        }
        
        // 利用setTimeout定时器,实现动画更新 
       function timeoutAnimate(){
            curTimeoutWidth = curTimeoutWidth + 3
            $setTimeoutDiv.css('width', curTimeoutWidth)
            if(curTimeoutWidth < maxWidth){
                timeout = setTimeout(timeoutAnimate, 16.7)
            }
        }

        // 利用setInterval定时器,实现动画更新 
       function intervalAnimate(){
            curIntervalWidth = curIntervalWidth + 3
            $setIntervalDiv.css('width', curIntervalWidth)
            if(curIntervalWidth >= maxWidth){
                clearInterval(interval)
            }
        }

        FrameAnimate()
        timeoutAnimate()
        interval = setInterval(intervalAnimate, 16.7)
    </script>
</body>
Logo

分享最新的 NVIDIA AI Software 资源以及活动/会议信息,精选收录AI相关技术内容,欢迎大家加入社区并参与讨论。

更多推荐