Clock
轻量的时间计时器,为动画提供「距离上一帧多久」与「从开始到现在多久」。
构造与属性
| 成员 | 默认 | 说明 |
|---|---|---|
autoStart | true | 首次读取 delta 时自动开始计时 |
startTime | 0 | 开始计时的时间戳 |
oldTime | 0 | 上一次读取的时间戳 |
elapsedTime | 0 | 累计经过时间 |
running | false | 是否正在计时 |
方法
| 方法 | 说明 |
|---|---|
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)。