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

ThreeJS技术问题:如何在mouseout时缩小被相交的对象

实现Three.js六边形鼠标移出缩小功能

我来给你梳理下具体的实现方案,因为Three.js的3D对象没有原生的mouseout事件,我们需要通过跟踪当前悬停的对象,结合射线检测的结果来模拟移出逻辑:

步骤1:声明全局变量跟踪悬停对象

首先需要一个变量来记录当前正被鼠标悬停的六边形,这样我们才能在鼠标离开时定位到它:

// 全局变量,记录当前悬停的六边形对象
let hoveredHex = null;
// 保留你的scaleTween变量,用来管理缩放动画避免冲突
let scaleTween = null;

步骤2:在鼠标移动事件中处理悬停/移出逻辑

把你的射线检测逻辑整合到鼠标移动事件里,每次检测相交结果后,对比当前悬停对象,判断是进入新对象、离开旧对象还是保持悬停:

function onMouseMove(event) {
  // 1. 计算鼠标在标准化设备坐标中的位置(Three.js射线检测必备)
  const mouse = new THREE.Vector2();
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

  // 2. 更新射线投射器
  raycaster.setFromCamera(mouse, camera);

  // 3. 检测与六边形对象的相交
  const intersects = raycaster.intersectObjects(hexObjects);

  // 4. 处理悬停与移出逻辑
  if (intersects.length > 0) {
    const currentHex = intersects[0].object; // 取最前面的相交对象

    // 如果当前悬停的对象和之前的不一样
    if (currentHex !== hoveredHex) {
      // 先处理之前的悬停对象:如果存在,就缩小它
      if (hoveredHex) {
        // 终止之前的动画避免冲突,再执行缩小
        if (scaleTween) scaleTween.kill();
        scaleTween = gsap.to(hoveredHex.scale, {
          duration: 0.3,
          x: 1, y: 1, z: 1, // 恢复原始缩放比例
          ease: "power2.out"
        });
      }

      // 设置新的悬停对象,执行放大动画
      hoveredHex = currentHex;
      document.body.style.cursor = 'pointer';
      if (scaleTween) scaleTween.kill();
      scaleTween = gsap.to(hoveredHex.scale, {
        duration: 0.3,
        x: 1.2, y: 1.2, z: 1.2, // 放大到1.2倍,可根据需求调整
        ease: "power2.out"
      });
    }
  } else {
    // 没有相交对象,说明鼠标离开了所有六边形
    if (hoveredHex) {
      // 缩小之前悬停的对象
      if (scaleTween) scaleTween.kill();
      scaleTween = gsap.to(hoveredHex.scale, {
        duration: 0.3,
        x: 1, y: 1, z: 1,
        ease: "power2.out"
      });
      hoveredHex = null; // 清空悬停记录
    }
    document.body.style.cursor = 'default'; // 恢复默认光标
  }
}

// 别忘了添加鼠标移动事件监听
window.addEventListener('mousemove', onMouseMove);

关键注意事项

  • 确保hexObjects是包含所有六边形Mesh的数组,且这些对象的visible和raycast属性是有效的(默认Mesh都支持射线检测)。
  • 如果不用GSAP,换成你当前使用的tween库即可,核心逻辑是在鼠标离开时将对象缩放重置为原始大小。
  • 每次创建新动画前终止旧动画(scaleTween.kill()),可以避免多个动画叠加导致的异常效果。

内容的提问来源于stack exchange,提问作者phun-ky

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:43:21