requestanimationframe 不会自动暂停,但主流浏览器在页面后台时通常降低或暂停其调用频率;应监听 visibilitychange 事件,结合 cancelanimationframe 和递归调用实现手动启停控制。

requestAnimationFrame 本身不会自动暂停,它依赖浏览器的渲染调度机制。当页面切换到后台(如切换标签页、最小化窗口),大多数现代浏览器会主动降低或停止 RAF 的调用频率,甚至完全暂停,以节省资源——但这不是规范强制要求的行为,而是浏览器的优化策略,且存在差异。
浏览器实际行为:暂停是“默认但不保证”
Chrome、Firefox、Edge 等主流浏览器在页面不可见时(document.hidden === true)通常会将 RAF 调度降为极低频率(如 1~2 次/秒)或暂停执行;Safari 在某些版本中可能仍保持较高频率。因此,不能依赖“浏览器一定会停”,必须主动检测并配合处理。
推荐做法:监听 visibilitychange + 手动控制循环
核心思路是:用 document.addEventListener('visibilitychange', ...) 捕获页面显隐状态,在隐藏时取消当前 RAF 请求,在显示时重新启动。
- 定义一个递归的动画函数,内部用
requestAnimationFrame自调用 - 用一个变量(如
let animationId = null)保存当前帧请求 ID - 页面隐藏时调用
cancelAnimationFrame(animationId) - 页面显示时重新调用动画函数启动循环
简单示例代码
let animationId = null;<br>let isRunning = false;<br><br>function animate() {<br> if (!isRunning) return;<br> // 执行你的动画逻辑(如更新时间、位置、重绘等)<br> console.log('frame');<br> animationId = requestAnimationFrame(animate);<br>}<br><br>// 页面显示时启动<br>function startAnimation() {<br> if (!isRunning) {<br> isRunning = true;<br> animate();<br> }<br>}<br><br>// 页面隐藏时停止<br>function stopAnimation() {<br> isRunning = false;<br> if (animationId) {<br> cancelAnimationFrame(animationId);<br> animationId = null;<br> }<br>}<br><br>// 监听可见性变化<br>document.addEventListener('visibilitychange', () => {<br> if (document.hidden) {<br> stopAnimation();<br> } else {<br> startAnimation();<br> }<br><br>// 初始化启动<br>if (!document.hidden) {<br> startAnimation();<br>}
补充建议:避免状态错乱与内存泄漏
- 确保每次只存在一个活跃的 RAF 循环,重复调用
requestAnimationFrame而不取消旧的会导致多帧叠加 - 如果使用类封装动画器,记得在页面卸载(
beforeunload或pagehide)时彻底清理 - 对音频、WebGL、Canvas 动画等耗资源操作,除了停 RAF,还应暂停音频上下文、减少绘制频率或释放临时缓冲区
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











