如何在不调用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
相关产品推荐
相关产品推荐

