如何使用Drei的CameraControls启用平移并禁用缩放与旋转
解决Drei CameraControls无法禁用缩放/旋转的问题
你的问题出在监听controlsRef的useEffect不会触发——因为React ref本身是稳定引用,仅current属性变化不会触发依赖controlsRef的useEffect执行,而组件挂载时controlsRef.current可能还未初始化完成,导致属性设置失效。
下面提供两种可靠解决方案:
方案一:利用useThree返回的controls实例
当给<CameraControls>设置makeDefault后,useThree()返回的controls会直接指向CameraControls实例,监听这个controls即可确保属性设置时机正确:
function Rig({ position = new THREE.Vector3(0, 0, 2), focus = new THREE.Vector3(0, 0, 0) }) { const { controls, scene } = useThree() const [, params] = useRoute('/item/:id') useEffect(() => { const active = scene.getObjectByName(params?.id) if (active) { active.parent.localToWorld(position.set(0, 0.5, 0.25)) active.parent.localToWorld(focus.set(0, 0, 5)) } controls?.setLookAt(...position.toArray(), ...focus.toArray(), true) }, [controls, scene, params?.id, focus, position]) useEffect(() => { if (controls) { // 禁用缩放和旋转,保留平移 controls.enableZoom = false controls.enablePan = true controls.enableRotate = false controls.update() } }, [controls]) // 依赖改为controls,确保实例就绪后执行 return <CameraControls makeDefault minPolarAngle={0} maxPolarAngle={Math.PI * 2} /> }
方案二:使用CameraControls的onReady回调
Drei的CameraControls提供onReady属性,会在控件完全初始化后触发,直接在这里配置属性:
function Rig({ position = new THREE.Vector3(0, 0, 2), focus = new THREE.Vector3(0, 0, 0) }) { const { scene } = useThree() const [, params] = useRoute('/item/:id') const controlsRef = useRef() useEffect(() => { const active = scene.getObjectByName(params?.id) if (active) { active.parent.localToWorld(position.set(0, 0.5, 0.25)) active.parent.localToWorld(focus.set(0, 0, 5)) } controlsRef.current?.setLookAt(...position.toArray(), ...focus.toArray(), true) }, [scene, params?.id, focus, position]) const handleControlsReady = (cameraControls) => { // 禁用缩放和旋转,保留平移 cameraControls.enableZoom = false cameraControls.enablePan = true cameraControls.enableRotate = false cameraControls.update() controlsRef.current = cameraControls } return ( <CameraControls ref={controlsRef} makeDefault minPolarAngle={0} maxPolarAngle={Math.PI * 2} onReady={handleControlsReady} /> ) }
两种方案都能确保在CameraControls实例就绪后修改属性,避免时机问题导致的设置失效,同时保留你需要的镜头过渡效果。
内容的提问来源于stack exchange,提问作者Yustina Yasin
相关产品推荐
相关产品推荐

