经纬志
首页 / three.js / API 文档

Clock

先看结论

轻量的时间计时器,为动画提供「距离上一帧多久」与「从开始到现在多久」。

最后验证 2026-11-03 · three.js 0.160.0 · 更新 2026-10-27 · 引用本文
new THREE.Clock(autoStart) → Clock

构造与属性

成员默认说明
autoStarttrue首次读取 delta 时自动开始计时
startTime0开始计时的时间戳
oldTime0上一次读取的时间戳
elapsedTime0累计经过时间
runningfalse是否正在计时

方法

方法说明
start()开始计时,重置起点
stop()停止计时,保留已累计的时间
getDelta()返回距上次调用的秒数,并把该值累加到 elapsedTime
getElapsedTime()内部会调用一次 getDelta(),返回累计时间
getStartTime()返回开始计时的时间戳

标准用法

const clock = new THREE.Clock();

renderer.setAnimationLoop(function () {
  // 标签页切回来时 delta 可能是几秒,截断上限避免动画瞬移
  const dt = Math.min(clock.getDelta(), 0.1);

  mesh.rotation.y += dt * 0.8;
  mesh.position.y = Math.sin(clock.elapsedTime * 1.4) * 0.3;

  renderer.render(scene, camera);
});

getDelta() 与 getElapsedTime() 每帧只能选一个主要调用。 两者都会推进内部时间戳,混用会让下一次 delta 变小,动画速度不稳定。

为什么必须截断 delta

浏览器在后台标签页里会降低 requestAnimationFrame 的频率,甚至暂停。 切回前台时,第一帧的 delta 可能是一分钟。用未截断的 delta 乘速度, 物体会瞬移几十米,相机也可能穿过建筑。

截断上限可以按场景设定:第一人称行走常用 0.1 秒,慢速展示动画可以用 0.05 秒。 这不是精度问题,而是稳定性问题。

暂停与恢复

// 暂停:停止累加
clock.stop();

// 恢复:从当前时刻继续,不清零已累计时间
clock.start();

// 需要完全重新计时:重设起点并清零累计值
clock.start();
clock.elapsedTime = 0;

stop() 之后调用 getDelta() 会返回 0,因此暂停期间动画自然停住。 如果业务上需要「暂停后继续」,把 running 标志与 Clock 的状态分开管理会更清晰, 演出类动画通常自己维护时间轴,不依赖 Clock。

多计时器与可暂停时间轴

Clock 只有一路时间。场景里同时存在多个独立节奏的动画时, addons 里的 Timer 支持多路计时与缩放,更适合做时间轴。 只驱动一个全局动画循环时,Clock 已经够用。

不要用帧数当时间。不同显示器刷新率从 60 到 144 赫兹不等, 按帧数累加的动画在高刷屏上会快一倍多。所有位移与旋转都应基于秒,而不是帧。

引用本文

经纬志(2026)。《Clock》。https://www.jingweizhi.com/three/api/clock.html(访问日期 2026-11-03)。