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

Three.js中鼠标移出物体后如何移除场景中的Mesh?

Three.js 鼠标悬停显示Mesh,移出后无法移除的问题解决

问题描述

加载GLTF模型后,已实现鼠标悬停时改变物体材质颜色、移出后恢复颜色的逻辑,但无法实现移出时移除悬停时创建的Mesh——Mesh始终留在场景中。尝试添加scene.remove(radioOutline.mesh)时,因radioOutline是if语句内的局部变量,外部无法访问;若将radioOutline相关代码移到if外,会因intersects[0]未定义抛出错误。

解决方案

核心是将radioOutline变量提升到onHover函数外部,让其作用域覆盖整个悬停逻辑,这样在鼠标移出时能访问并移除该Mesh。

修改后的代码

var radioMaterial = new THREE.MeshBasicMaterial({color: 0x0fffAA, side: THREE.BackSide});
class outlineMesh {
    constructor(geometry) {
        this.mesh = new THREE.Mesh(geometry, radioMaterial);
    }
}

// 声明全局(函数外)变量存储outline实例,初始为null
let radioOutline = null;

// Mouse hover event -> raycaster 
function onHover(event) {
    event.preventDefault();
    raycaster.setFromCamera( mouse, camera );
    var intersects = raycaster.intersectObject( radioModel );

    if ( intersects.length > 0 ) {
        // 仅当outline不存在时才创建,避免重复添加
        if (!radioOutline) {
            radioOutline = new outlineMesh(intersects[0].object.geometry);
            radioOutline.mesh.position.set(1.4,-0.5,1.2);
            radioOutline.mesh.rotation.y = -0.3;
            radioOutline.mesh.scale.multiplyScalar(1.6);
            scene.add(radioOutline.mesh);
        }

        if ( intersects[0].object != INTERSECTED ) {
            if ( INTERSECTED ) {
                INTERSECTED.material.color.setHex(INTERSECTED.currentHex);
            }
            INTERSECTED = intersects[0].object;
            INTERSECTED.currentHex = INTERSECTED.material.color.getHex();
            INTERSECTED.material.color.setHex(radioHoverColor);
            cursor.style.cursor = "pointer";
            
        }
    }
    else {
        if ( INTERSECTED ) {
            INTERSECTED.material.color.setHex(INTERSECTED.currentHex);
        }
        // 移除outline并重置变量
        if (radioOutline) {
            scene.remove(radioOutline.mesh);
            radioOutline = null;
        }
        INTERSECTED = null;
        cursor.style.cursor = "default";
    }
}

关键修改点

  • 变量作用域调整:将radioOutline从if内部的局部变量改为函数外的全局变量,确保鼠标移出时能访问到该实例。
  • 避免重复创建:悬停时先判断radioOutline是否存在,不存在才创建添加,防止同一Mesh被重复添加到场景。
  • 移出时清理:在else分支中,检查radioOutline存在则从场景移除,并将变量重置为null,确保下次悬停能重新创建。

内容的提问来源于stack exchange,提问作者ZIMRO

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 07:27:30