You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Three.js是否提供模拟相机在点位间移动的内置函数?

实现Three.js相机平滑移动的几种方案

当然有办法替代生硬的相机瞬移,实现平滑的点位过渡!下面给你几个Three.js生态里常用的实用方案,按需选择就行:

1. Tween.js(最流行的补间动画方案)

Tween.js是Three.js社区里使用率极高的补间库,专门用来处理属性的平滑过渡,API简单直观,适合快速实现相机移动效果。

示例代码

// 先引入Tween.js(npm安装的话用 import TWEEN from '@tweenjs/tween.js')
// 定义目标位置和轨道控制器的目标点
const targetCameraPos = new THREE.Vector3(0, 100, -350);
const targetControlsTarget = new THREE.Vector3(0, 0, 0);

// 给相机位置创建补间动画
new TWEEN.Tween(camera.position)
  .to(targetCameraPos, 1000) // 1000毫秒(1秒)完成过渡
  .easing(TWEEN.Easing.Quadratic.InOut) // 用缓动函数让动画更自然,避免生硬
  .start();

// 给轨道控制器的目标点创建补间动画
new TWEEN.Tween(orbitControls.target)
  .to(targetControlsTarget, 1000)
  .easing(TWEEN.Easing.Quadratic.InOut)
  .onUpdate(() => {
    orbitControls.update(); // 每次更新后必须刷新控制器,否则视角会卡顿
  })
  .start();

// 别忘了在你的动画循环里加入TWEEN.update()
function animate() {
  requestAnimationFrame(animate);
  TWEEN.update(); // 驱动所有补间动画
  renderer.render(scene, camera);
}

2. Three.js原生AnimationSystem(适合复杂动画联动)

如果你不想引入额外依赖,Three.js自带的动画系统也能实现这个效果,适合需要和模型动画、场景其他元素同步的复杂场景。

示例代码

// 先创建一个Clock实例用来计算时间差
const clock = new THREE.Clock();

// 创建相机位置的关键帧轨道
const cameraPosTrack = new THREE.VectorKeyframeTrack(
  '.position',
  [0, 1], // 时间轴:0秒开始,1秒结束
  [
    camera.position.x, camera.position.y, camera.position.z, // 起始位置
    0, 100, -350 // 目标位置
  ]
);

// 创建轨道控制器目标点的关键帧轨道
const controlsTargetTrack = new THREE.VectorKeyframeTrack(
  '.target',
  [0, 1],
  [
    orbitControls.target.x, orbitControls.target.y, orbitControls.target.z, // 起始目标点
    0, 0, 0 // 目标目标点
  ]
);

// 组装动画剪辑和混合器
const cameraMoveClip = new THREE.AnimationClip('smoothCameraMove', 1, [cameraPosTrack, controlsTargetTrack]);
const mixer = new THREE.AnimationMixer(camera); // 将混合器绑定到相机对象
const action = mixer.clipAction(cameraMoveClip);

// 启动动画
action.play();

// 在动画循环里更新混合器
function animate() {
  requestAnimationFrame(animate);
  const deltaTime = clock.getDelta();
  mixer.update(deltaTime); // 驱动动画更新
  orbitControls.update();
  renderer.render(scene, camera);
}

3. 手动线性插值(轻量无依赖方案)

如果你的场景很简单,不想引入任何库,也可以手动在每一帧做线性插值,这种方式最轻量化,完全可控。

示例代码

const targetCameraPos = new THREE.Vector3(0, 100, -350);
const targetControlsTarget = new THREE.Vector3(0, 0, 0);
const moveSpeed = 0.05; // 控制移动速度,值越大移动越快,0.05左右比较自然

function animate() {
  requestAnimationFrame(animate);
  
  // 相机位置线性插值
  camera.position.lerp(targetCameraPos, moveSpeed);
  // 轨道控制器目标点线性插值
  orbitControls.target.lerp(targetControlsTarget, moveSpeed);
  
  orbitControls.update();
  renderer.render(scene, camera);
}

方案选择建议

  • 优先选Tween.js:API简单,灵活度高,适合大多数场景;
  • 选原生AnimationSystem:需要和其他动画同步,或者不想加额外依赖时;
  • 选手动插值:小项目、轻量需求,追求极致精简时。

内容的提问来源于stack exchange,提问作者zombierecord

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 11:47:34