贝利信息

javascript如何实现动画效果_requestAnimationFrame优势在哪?

日期:2026-01-15 00:00 / 作者:幻影之瞳
requestAnimationFrame 是浏览器原生 API,用于在下一次重绘前执行动画回调;它由浏览器调度,自动适配刷新率、后台暂停、节电状态,避免 setTimeout 的定时不准、后台耗电、不同步丢帧等问题。

requestAnimationFrame 是什么,为什么比 setTimeout 更适合动画

requestAnimationFrame 是浏览器提供的原生 API,用于在下一次重绘前执行回调函数。它不是“自己控制帧率”,而是把动画逻辑交给浏览器调度——浏览器知道当前刷新率(比如 60Hz)、是否页面在后台、设备节电状态等,自动决定何时触发回调。

setTimeoutsetInterval 模拟 60fps(即每 16.6ms 执行一次)看似可行,但实际会出问题:

requestAnimationFrame 天然规避这些——它只在浏览器准备重绘前调用,且页面隐藏时自动暂停。

最简可用的 requestAnimationFrame 动画写法

核心是「递归调用 + 状态更新」。不要把它当成一次性函数,而是一个持续驱动的循环入口。

let startTime = null;
const duration = 2000; // 动画总时长 2s

function animate(currentTime) { if (!startTime) startTime = currentTime; const elapsed = currentTime - startTime; const progress = Math.min(elapsed / duration, 1); // 归一化进度 [0, 1]

// 更新元素位置(示例:水平移动) const element = document.getElementById('box'); element.style.transform = translateX(${progress * 300}px);

if (progress < 1) { requestAnimationFrame(animate); // 继续下一帧 } }

// 启动 requestAnimationFrame(animate);

注意点:

requestAnimationFrame 在 CSS 动画和 JS 动画中的定位

它不替代 CSS @keyframes,而是补充那些 CSS 做不了的事:比如跟随鼠标实时计算路径、物理模拟(弹性、重力)、滚动视差、Canvas 绘图动画等。

关键区别:

常见误用:用它反复设置 element.style.left/top 触发 layout → paint → composite 全流程。应优先用 transformopacity,它们只触发 composite,更轻量。

容易被忽略的兼容性与清理问题

requestAnimationFrame 在现代浏览器中已无兼容问题(IE10+ 支持,且有成熟 polyfill),但两个细节常被跳过:

例如,一个轮播组件切换时没 cancel 上一个 requestAnimationFrame,旧动画回调仍可能执行并覆盖新状态——这种竞态很难 debug。