🔥Three.js轮廓线高亮神器来啦!自定义高亮选中效果只需一个类搞定!

🔥Three.js轮廓线高亮神器来啦!自定义高亮选中效果只需一个类搞定!

在开发 Three.js 项目的过程中,很多人都会遇到这样一个需求------如何高亮选中某个物体?

我们希望用户点击一个模型,它能"亮起来",视觉上突出显示,这样不仅提升交互体验,也让整体项目看起来更"高级"。

🎯 本文将手把手带你封装一个支持多物体、可配置、易管理 的轮廓线系统,使用 Three.js 中的 OutlinePass 实现,只需一句话即可启用高亮选中效果!


✅ 轮廓线效果到底是啥?

轮廓线(Outline)是一种通过为选中的物体描边来增强视觉效果的技术。在 Three.js 中,我们可以借助 EffectComposerOutlinePass 来实现。

如下图所示(官方示例) 👇,添加了轮廓线的物体会被边缘描边勾勒出来,非常醒目:

✨ 功能亮点

我们将封装成一个 CustomOutline 类,具有以下特点:

  • 多物体高亮支持,可批量添加或删除选中对象
  • 动态启用/禁用轮廓线效果(比如切换编辑/预览模式)
  • 支持可配置参数(颜色、粗细、透明度等)
  • 释放资源、自动清理引用,适配复杂项目

📦 核心依赖

你需要先安装/引入以下 Three.js 扩展:

js 复制代码
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js'
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js'
import { OutlinePass } from 'three/examples/jsm/postprocessing/OutlinePass.js'
import { OutputPass } from 'three/examples/jsm/postprocessing/OutputPass.js'

🧠 类的核心结构一览

我们将封装一个 CustomOutline 类,支持以下方法:

方法名 功能说明
addSelectedObjects(obj) 添加高亮对象
removeSelectedObjects(obj) 移除高亮对象
clearSelectedObjects() 清除所有高亮
setOutlineParameters(options) 设置描边参数
enable() / disable() 启用/关闭描边
render() 每帧渲染时调用
dispose() 释放资源
setSize(width, height) 自适应画布大小

📄 使用示例

js 复制代码
// 初始化
const outline = new CustomOutline(scene, camera, renderer)

// 设置轮廓线参数
outline.setOutlineParameters({
  edgeStrength: 5,
  edgeThickness: 2,
  visibleEdgeColor: '#00ffff',
})

// 添加选中高亮的物体
outline.addSelectedObjects(mesh)

// 渲染循环中调用
function animate() {
  requestAnimationFrame(animate)
  outline.render()
}

✅ 小提示 :你还可以动态设置 visibleEdgeColorhiddenEdgeColor 来实现不同状态下的风格变化!


💡 适用场景

  • 模型编辑器中的物体选中反馈
  • 三维配置器中高亮显示部件
  • 智慧矿山、数字孪生等系统中的对象标识
  • 教学可视化、模型拆解引导

📁 完整源码

js 复制代码
/**
 * CustomOutline 类 - Three.js 的轮廓线效果管理器
 * 提供了一个完整的轮廓线效果系统,支持:
 * - 可配置的轮廓线参数(颜色、宽度、透明度等)
 * - 多个物体的轮廓线效果
 * - 独立控制物体的轮廓线效果
 * - 动态启用/禁用轮廓线系统
 */

import * as THREE from 'three'
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js'
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js'
import { OutlinePass } from 'three/examples/jsm/postprocessing/OutlinePass.js'
import { OutputPass } from 'three/examples/jsm/postprocessing/OutputPass.js'

/**
 * 默认的轮廓线效果参数配置
 */
const DEFAULT_OUTLINE_OPTIONS = {
  edgeStrength: 3.0, // 轮廓线强度
  edgeGlow: 0.0, // 轮廓线发光强度
  edgeThickness: 1.0, // 轮廓线粗细
  pulsePeriod: 0, // 轮廓线闪烁周期(0为不闪烁)
  usePatternTexture: false, // 是否使用纹理
  visibleEdgeColor: new THREE.Color(0xffffff), // 可见部分轮廓线颜色
  hiddenEdgeColor: new THREE.Color(0x190a05), // 被遮挡部分轮廓线颜色
  opacity: 1.0, // 轮廓线透明度
}

export default class CustomOutline {
  /**
   * 创建一个新的轮廓线效果实例
   * @param {THREE.Scene} scene - Three.js 场景实例
   * @param {THREE.Camera} camera - Three.js 相机实例
   * @param {THREE.WebGLRenderer} renderer - Three.js 渲染器实例
   */
  constructor(scene, camera, renderer) {
    this._scene = scene
    this._camera = camera
    this._renderer = renderer
    this._selectedObjects = []
    this._enabled = true

    this._initOutlineEffect()
  }

  /**
   * 初始化轮廓线效果的各个组件
   * @private
   */
  _initOutlineEffect() {
    // 创建效果合成器
    this._composer = new EffectComposer(this._renderer)

    // 添加场景渲染通道
    const renderPass = new RenderPass(this._scene, this._camera)
    this._composer.addPass(renderPass)

    // 创建轮廓线通道
    this._outlinePass = new OutlinePass(
      new THREE.Vector2(window.innerWidth, window.innerHeight),
      this._scene,
      this._camera,
    )

    // 设置默认参数
    this.setOutlineParameters()

    // 添加轮廓线通道
    this._composer.addPass(this._outlinePass)

    // 添加输出通道
    const outputPass = new OutputPass()
    this._composer.addPass(outputPass)
  }

  /**
   * 更新轮廓线效果的参数配置
   * @param {Object} options - 轮廓线参数配置对象
   */
  setOutlineParameters(options = {}) {
    const params = { ...DEFAULT_OUTLINE_OPTIONS, ...options }

    Object.entries(params).forEach(([key, value]) => {
      if (key in this._outlinePass) {
        this._outlinePass[key] = value
      }
    })
  }

  /**
   * 添加要显示轮廓线的物体
   * @param {THREE.Object3D|Array<THREE.Object3D>} objects - 要添加轮廓线的物体或物体数组
   */
  addSelectedObjects(objects) {
    const objectsArray = Array.isArray(objects) ? objects : [objects]

    objectsArray.forEach((object) => {
      if (!this._selectedObjects.includes(object)) {
        this._selectedObjects.push(object)
      }
    })

    this._outlinePass.selectedObjects = this._selectedObjects
  }

  /**
   * 移除物体的轮廓线效果
   * @param {THREE.Object3D|Array<THREE.Object3D>} objects - 要移除轮廓线的物体或物体数组
   */
  removeSelectedObjects(objects) {
    const objectsArray = Array.isArray(objects) ? objects : [objects]

    this._selectedObjects = this._selectedObjects.filter(
      (selected) => !objectsArray.includes(selected),
    )

    this._outlinePass.selectedObjects = this._selectedObjects
  }

  /**
   * 清除所有轮廓线效果
   */
  clearSelectedObjects() {
    this._selectedObjects = []
    this._outlinePass.selectedObjects = []
  }

  /**
   * 获取当前所有具有轮廓线效果的物体
   * @returns {Array<THREE.Object3D>} 具有轮廓线效果的物体数组
   */
  getSelectedObjects() {
    return [...this._selectedObjects]
  }

  /**
   * 更新轮廓线效果的渲染尺寸
   * @param {number} width - 新的渲染宽度
   * @param {number} height - 新的渲染高度
   */
  setSize(width, height) {
    this._composer.setSize(width, height)
  }

  /**
   * 设置轮廓线的可见边缘颜色
   * @param {THREE.Color|string|number} color - 新的颜色值
   */
  setVisibleEdgeColor(color) {
    this._outlinePass.visibleEdgeColor = new THREE.Color(color)
  }

  /**
   * 设置轮廓线的隐藏边缘颜色
   * @param {THREE.Color|string|number} color - 新的颜色值
   */
  setHiddenEdgeColor(color) {
    this._outlinePass.hiddenEdgeColor = new THREE.Color(color)
  }

  /**
   * 销毁轮廓线效果,释放资源
   */
  dispose() {
    this.clearSelectedObjects()
    this._outlinePass.dispose()
    this._composer.dispose()

    // 清理引用
    this._outlinePass = null
    this._composer = null
    this._selectedObjects = null
  }

  /**
   * 临时禁用轮廓线效果,但保留配置
   */
  disable() {
    this._enabled = false
  }

  /**
   * 重新启用之前禁用的轮廓线效果
   */
  enable() {
    this._enabled = true
  }

  /**
   * 执行轮廓线效果的渲染
   */
  render() {
    if (!this._enabled) {
      // 如果禁用了轮廓线效果,直接使用普通渲染
      this._renderer.render(this._scene, this._camera)
      return
    }

    this._composer.render()
  }
}

🔚 结语

Three.js 是一个强大的 3D 渲染引擎,而 OutlinePass 的轮廓线效果则能为你的项目增添视觉亮点与交互体验。

希望这个封装类能帮你节省时间、提升项目质量。

📌 喜欢就点个赞 👍,关注我!

相关推荐
OEC小胖胖4 小时前
去中心化身份:2025年Web3身份验证系统开发实践
前端·web3·去中心化·区块链
vvilkim5 小时前
Electron 进程间通信(IPC)深度优化指南
前端·javascript·electron
ai小鬼头7 小时前
百度秒搭发布:无代码编程如何让普通人轻松打造AI应用?
前端·后端·github
漂流瓶jz7 小时前
清除浮动/避开margin折叠:前端CSS中BFC的特点与限制
前端·css·面试
前端 贾公子7 小时前
在移动端使用 Tailwind CSS (uniapp)
前端·uni-app
散步去海边7 小时前
Cursor 进阶使用教程
前端·ai编程·cursor
清幽竹客7 小时前
vue-30(理解 Nuxt.js 目录结构)
前端·javascript·vue.js
weiweiweb8887 小时前
cesium加载Draco几何压缩数据
前端·javascript·vue.js
幼儿园技术家7 小时前
微信小店与微信小程序简单集成指南
前端
我不吃饼干9 天前
鸽了六年的某大厂面试题:你会手写一个模板引擎吗?
前端·javascript·面试