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

解决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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 05:36:22