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

Three.js对象颜色高亮与还原异常问题求助

问题诊断与修复方案

核心问题分析

你的代码存在几个关键问题,导致颜色无法正确还原甚至变黑:

  1. 未处理多材质场景:如果Mesh的material是数组(比如一个Mesh使用多个材质渲染不同面),直接访问node.material.color会抛出错误,导致颜色设置失败,最终显示黑色。
  2. unhighlightJob未检查材质存在性:若Mesh没有绑定材质,访问node.material.color会引发异常,导致颜色异常。
  3. 高亮逻辑依赖当前颜色而非原始颜色:重复调用highlightJob时,会基于已经高亮过的颜色(已被Three.js clamp到1)再次放大,虽然不影响还原,但会导致高亮效果不符合预期。

修复后的代码

1. 高亮函数(highlightJob)

修改为支持多材质,且每次高亮都基于原始颜色,避免重复放大的问题:

async highlightJob(job) {
  try {
    return new Promise((resolve) => {
      const objects = job.objects instanceof THREE.Group ? job.objects.children : job.objects;
      for (const object of objects) {
        object?.traverse(node => {
          if (node instanceof THREE.Mesh && node.material) {
            // 存储原始颜色:处理单个材质或材质数组
            if (!node.userData.originalColor) {
              if (Array.isArray(node.material)) {
                node.userData.originalColor = node.material.map(mat => mat.color.clone());
              } else {
                node.userData.originalColor = node.material.color.clone();
              }
            }
            // 执行高亮:基于原始颜色放大,而非当前颜色
            const applyHighlight = (mat, originalColor) => {
              const newColor = originalColor.clone().multiplyScalar(5);
              mat.color.copy(newColor);
              mat.needsUpdate = true; // 通知Three.js材质已更新
            };
            if (Array.isArray(node.material)) {
              node.material.forEach((mat, idx) => {
                applyHighlight(mat, node.userData.originalColor[idx]);
              });
            } else {
              applyHighlight(node.material, node.userData.originalColor);
            }
          }
        });
      }
      resolve();
    });
  } catch (error) {
    throw new Error(`Error in highlightJob: ${error.message}`);
  }
}

2. 取消高亮函数(unhighlightJob)

增加材质存在性检查,支持多材质还原:

async unhighlightJob(job) {
  try {
    if (!job) return null;
    return new Promise((resolve) => {
      const objects = job.objects instanceof THREE.Group ? job.objects.children : job.objects;
      for (const object of objects) {
        object?.traverse(node => {
          if (node instanceof THREE.Mesh && node.material && node.userData.originalColor) {
            // 还原原始颜色:处理单个材质或材质数组
            const restoreColor = (mat, originalColor) => {
              mat.color.copy(originalColor);
              mat.needsUpdate = true; // 通知Three.js材质已更新
            };
            if (Array.isArray(node.material)) {
              node.material.forEach((mat, idx) => {
                restoreColor(mat, node.userData.originalColor[idx]);
              });
            } else {
              restoreColor(node.material, node.userData.originalColor);
            }
          }
        });
      }
      resolve();
    });
  } catch (error) {
    throw new Error(`Error in unhighlightJob: ${error.message}`);
  }
}

额外注意事项

  • 共享材质问题:如果多个Mesh共享同一个材质实例,修改颜色会同时影响所有共享该材质的Mesh。若你的场景存在共享材质,建议在高亮时为每个Mesh创建材质的副本(node.material = node.material.clone()),避免跨任务的颜色干扰。
  • 颜色溢出处理:multiplyScalar(5)会让RGB值远超1,Three.js会自动将其clamp到1(显示为白色)。如果需要更柔和的高亮效果,可以改用addScalar或者调整放大系数,比如multiplyScalar(1.5),避免颜色过曝。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 03:16:17