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
相关产品推荐
相关产品推荐

