解决Three.js中拖拽操作时误触发点击事件的问题
解决Three.js拖拽后误触发点击聚焦的问题
问题说明
在Three.js中加载多对象GLTF模型后,设置了点击对象时相机缩放聚焦的交互,但拖拽操作松开鼠标后仍会触发点击事件,导致相机错误聚焦。尝试通过dragged变量结合嵌套判断修复,但未生效。
问题根源
原来的代码存在几个关键问题:
- 将
mousedown、mousemove、mouseup事件监听嵌套在onClick函数内部,每次点击都会重复绑定事件,导致状态逻辑混乱 dragged是局部变量,无法在事件回调间正确共享状态onClick事件与mouseup回调嵌套,事件触发顺序和逻辑冲突
修复方案
将状态变量和事件监听移到全局作用域,统一管理拖拽状态,同时优化点击逻辑避免重复判断:
var mesh = []; const raycaster = new THREE.Raycaster(); const mouse = new THREE.Vector2(); // 全局拖拽状态标记 let dragged = false; // 初始化时绑定一次事件,避免重复绑定 window.addEventListener('mousedown', () => { dragged = false; }); window.addEventListener('mousemove', () => { dragged = true; }); function onClick(event) { event.preventDefault(); // 如果是拖拽后触发的点击,直接返回 if (dragged) { dragged = false; // 重置状态,避免影响下一次操作 return; } mouse.x = (event.clientX / window.innerWidth) * 2 - 1; mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; raycaster.setFromCamera(mouse, camera); const intersects = raycaster.intersectObjects(scene.children, true); if (intersects.length === 0) return; const targetName = intersects[0].object.name; // 处理聚焦逻辑 if (targetName === "Tree006" || targetName === "Tree001") { const targetPos = mesh[targetName].position; zoomInTimeline(targetPos.x, targetPos.y, targetPos.z, 5); console.log('Intersection:', intersects[0]); } else { // 点击其他区域返回默认视角 gsap.to(camera.position, { duration: 1, x: 6, y: 4, z: 4, onUpdate: () => { controls.enabled = true; } }); } }
关键优化点
- 将
dragged设为全局变量,确保事件回调间状态共享 - 在初始化时仅绑定一次鼠标事件,避免重复绑定导致的逻辑混乱
- 在
onClick开头判断拖拽状态,若为拖拽触发则直接返回并重置状态 - 合并重复的点击判断逻辑,减少冗余代码
内容的提问来源于stack exchange,提问作者gjjr
相关产品推荐
相关产品推荐

