在 requestanimationframe 回调中应直接使用参数 currenttime 计算帧间隔 Δt(毫秒),避免 date.now();首次调用跳过计算,需除以 1000 转为秒以支持时间驱动逻辑。

在 requestAnimationFrame 回调中获取每帧的时间差,核心是利用浏览器传入的 高精度时间戳(DOMHighResTimeStamp),它以毫秒为单位,精确到微秒(实际精度通常为 0.1–1ms),比 Date.now() 更可靠。
直接使用回调参数中的时间戳
requestAnimationFrame 的回调函数会自动接收一个参数 —— 当前帧的 时间戳(自页面加载以来的毫秒数,基于 performance.timeOrigin)。这是最推荐、最准确的方式:
- 无需手动调用
performance.now() - 该时间戳与
performance.now()同源,具有单调性与高精度 - 避免了多次调用带来的微小开销和潜在时序偏差
保存上一帧时间戳并相减
在回调中用闭包或模块变量保存上一帧时间,当前帧时间减去上一帧时间即得 Δt(单位:毫秒):
let lastTime = 0;
<p>function animate(currentTime) {
if (lastTime !== 0) {
const deltaTime = currentTime - lastTime; // 单位:毫秒
console.log('帧间隔:', deltaTime.toFixed(2), 'ms');
// 例如:用于物理模拟、动画速度控制等
}
lastTime = currentTime;
requestAnimationFrame(animate);
}</p><p>requestAnimationFrame(animate);
</p>
注意时间单位与常见误区
Δt 默认单位是毫秒,如需秒级计算(如速度、加速度),需除以 1000:
const deltaSeconds = deltaTime / 1000;- 不要用
Date.now()或new Date().getTime()替代 —— 它们精度低、可能跳变、且不与 RAF 同步 - 首次调用时
lastTime未定义,应跳过 Δt 计算(或设为currentTime,但更推荐跳过首帧) - Δt 不恒定(60fps ≈ 16.67ms),需按实际值做时间驱动逻辑,而非假设固定帧率
可选:封装成带 Δt 的动画循环工具
为复用方便,可封装一个简单 runner:
function startAnimation(update) {
let last = 0;
function loop(current) {
const delta = last ? current - last : 0;
last = current;
update(delta); // 传入毫秒级时间差
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
}
<p>// 使用
startAnimation((dt) => {
object.x += velocity * (dt / 1000); // 转为秒,实现帧率无关移动
});
</p>前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











