Three.js使用DragControls拖动时如何将相机子立方体转移至场景
解决方案
有两种无需修改DragControls源码的实现方式,优先推荐第二种:
方案1:手动修正DragControls内部偏移量
DragControls的_offset属性虽然是私有命名,但可以直接访问覆盖。你只需要在调整完对象父级和位置后,重新计算正确的偏移量覆盖原有值即可:
dragControls.addEventListener( 'dragstart', function (event) { orbitControls.enabled = false; const obj = event.object; const vec3 = new THREE.Vector3(); if(obj.parent.type === "OrthographicCamera") { // 保存点击位置的世界坐标 const clickWorldPos = dragControls._pickedPoint.clone(); // 转移父级并更新位置 scene.attach(obj); obj.position.set(5, 0, 0); obj.updateMatrixWorld(true); // 重新计算正确偏移量 obj.getWorldPosition(vec3); dragControls._offset.copy(clickWorldPos).sub(vec3); } } );
方案2:捕获阶段提前处理父级转移
利用DOM事件的捕获优先机制,在DragControls的mousedown事件触发前就完成对象父级转移和位置更新,这样DragControls计算偏移时用的就是最新的正确状态:
// 提前初始化射线和鼠标向量复用 const raycaster = new THREE.Raycaster(); const mouse = new THREE.Vector2(); const targetCube = /* 你的立方体对象 */; // 绑定捕获阶段的mousedown事件,优先级高于DragControls的冒泡阶段监听 renderer.domElement.addEventListener('mousedown', (e) => { // 计算鼠标标准化坐标 mouse.x = (e.clientX / window.innerWidth) * 2 - 1; mouse.y = -(e.clientY / window.innerHeight) * 2 + 1; // 射线检测判断是否点击了目标立方体 raycaster.setFromCamera(mouse, camera); const intersects = raycaster.intersectObject(targetCube); if (intersects.length) { const obj = intersects[0].object; if (obj.parent.type === "OrthographicCamera") { scene.attach(obj); obj.position.set(5, 0, 0); obj.updateMatrixWorld(true); } } }, true); // 第三个参数设为true表示启用捕获阶段监听
方案2完全使用Three.js公开API实现,不依赖
DragControls的内部属性命名,后续版本升级也不会出现兼容性问题,是更稳定的选择。
内容的提问来源于stack exchange,提问作者David B
相关产品推荐
相关产品推荐

