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

Three.js中实现几何体悬停与选中状态效果的最优方案

单OutlinePass实现三种交互状态的最优方案

不用两个OutlinePass,核心思路是复用单个OutlinePass,通过动态切换目标对象数组和修改轮廓参数(比如是否启用patternTexture)来区分正常、悬停、选中三种状态,具体实现步骤如下:

1. 初始化基础配置

只创建一个OutlinePass,默认不显示轮廓(对应正常状态),同时维护两个数组分别记录悬停和选中的对象:

// 初始化OutlinePass
const outlinePass = new THREE.OutlinePass(new THREE.Vector2(window.innerWidth, window.innerHeight), scene, camera);
// 默认无目标对象,不显示轮廓
outlinePass.selectedObjects = [];
// 保存patternTexture,后续按需启用
const patternTexture = new THREE.TextureLoader().load('你的纹理路径');
// 维护状态数组
let hoverObjects = [];
let selectedObjects = [];
// 将OutlinePass添加到后期处理管道
composer.addPass(outlinePass);

2. 处理交互事件

用Raycaster实现悬停和选中的对象检测:

const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();

// 鼠标移动事件 - 检测悬停对象
window.addEventListener('mousemove', (event) => {
  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);
  
  // 更新悬停数组:只保留第一个相交对象(如果有)
  hoverObjects = intersects.length > 0 ? [intersects[0].object] : [];
});

// 点击事件 - 切换选中状态
window.addEventListener('click', () => {
  if (hoverObjects.length === 0) return;
  
  const target = hoverObjects[0];
  const index = selectedObjects.findIndex(obj => obj === target);
  if (index > -1) {
    // 已选中则取消
    selectedObjects.splice(index, 1);
  } else {
    // 未选中则添加
    selectedObjects.push(target);
  }
});

3. 每帧动态更新OutlinePass状态

在render循环中,根据选中/悬停的优先级(选中 > 悬停 > 正常)修改OutlinePass的参数:

function render() {
  requestAnimationFrame(render);
  
  // 状态优先级判断
  if (selectedObjects.length > 0) {
    // 选中状态:启用pattern纹理,目标设为选中对象
    outlinePass.selectedObjects = selectedObjects;
    outlinePass.patternTexture = patternTexture;
    outlinePass.visibleEdgeColor.set('#ff0000'); // 可自定义选中轮廓颜色
  } else if (hoverObjects.length > 0) {
    // 悬停状态:关闭pattern纹理,目标设为悬停对象
    outlinePass.selectedObjects = hoverObjects;
    outlinePass.patternTexture = null;
    outlinePass.visibleEdgeColor.set('#00ff00'); // 可自定义悬停轮廓颜色
  } else {
    // 正常状态:无目标对象,不显示轮廓
    outlinePass.selectedObjects = [];
  }
  
  composer.render();
}
render();

方案优势

  • 避免了两个OutlinePass带来的额外渲染开销,减少GPU和内存占用
  • 逻辑集中,状态切换更可控,后期维护成本更低
  • 可以灵活调整不同状态的轮廓颜色、纹理等参数,扩展性强

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 15:52:10