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

如何在不调用controls.update()的情况下启用Three.js阻尼效果?

问题解决思路

核心问题是OrbitControls.update()会实时同步相机状态与自身的target/参数,当你用GSAP动画相机位置时,controls的更新会和你的手动相机操作(lookAt)冲突,导致场景异常。

以下是具体修复步骤:

1. 正确启用阻尼并保留update()

首先确保你已经开启了阻尼,然后必须在tick函数里调用controls.update()——阻尼效果依赖每帧更新:

// 初始化controls时开启阻尼
controls.enableDamping = true;

// tick函数里保留update
const tick = () => {
  const elapsedTime = clock.getElapsedTime()
  controls.update() // 必须保留,阻尼需要这个
  renderer.render(scene, camera)
  window.requestAnimationFrame(tick)
}

2. 动画期间隔离controls与相机

在GSAP动画相机时,暂时禁用controls的整体功能,避免它干扰相机的动画:

projectDirect.element.addEventListener('click', (e) => {
  // 先保存当前controls的状态,方便后续恢复
  const prevEnableRotate = controls.enableRotate;
  const prevEnableZoom = controls.enableZoom;
  const prevEnablePan = controls.enablePan;

  // 完全禁用controls,阻止它更新相机
  controls.enabled = false;

  e.stopPropagation();
  gsap.to(camera.position, {
    duration: 1.5,
    x: aboutCenter.x + 8,
    y: aboutCenter.y,
    z: aboutCenter.z,
    onUpdate: function () {
      camera.lookAt(aboutCenter);
    },
    // 动画结束后恢复controls,并同步target
    onComplete: () => {
      // 同步controls的target和相机lookAt的目标
      controls.target.copy(aboutCenter);
      // 恢复之前的交互权限
      controls.enableRotate = prevEnableRotate;
      controls.enableZoom = prevEnableZoom;
      controls.enablePan = prevEnablePan;
      // 重新启用controls
      controls.enabled = true;
      // 强制更新一次,让controls状态同步
      controls.update();
    }
  });
})

3. 为什么之前设置target没用?

之前单独设置controls.target没效果,是因为:

  • 你没在设置后调用controls.update()同步状态
  • 动画期间controls还在运行,会覆盖你设置的target

通过上面的步骤,在动画结束后同步target并调用update,就能让controls的目标和相机保持一致,后续操作不会出现偏移。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 03:55:14