从一个开源风机大屏,看懂前端 3D 可视化的完整套路

项目:MF-TurbineMonitor (一个大型涡轮扇叶风力发电机数据大屏案例,Vue3 技术栈,作者 fengtianxi001)

GitHub:https://github.com/fengtianxi001/MF-TurbineMonitor

在线体验:https://fengtianxi001.github.io/MF-TurbineMonitor

最值得抄的不是炫酷效果,而是分层思路------Three.js 场景、设备业务、图表封装拆成三个 hooks,用 provide/inject 串事件。

01 这是什么

无后端、数据全 mock 的前端视觉案例,核心卖点是"3D 设备 + 数据面板 + 拆解动画":

  • 中间:可旋转/缩放/点击/拆解的 3D 风机
  • 左侧:参数监测、历史功率、日发电量图表
  • 右侧:运行监测、故障对比、偏航角度;点零件切换为详情面板
  • 底部:设备告警(随机零件变红 + 镜头推近)、设备拆解

技术栈:Vue3 + TS + Vite + Three.js + ECharts + TWEEN + mockjs + autofit.js。

02 架构:三个 hooks

复制代码
useThree.ts    # 纯 3D:场景/相机/渲染/拾取/特效,不管"风机"是啥
useTurbine.ts  # 业务层:模型加载/拆解/告警
useEcharts.ts  # 图表层:init/setOption/resize

改造成其他设备只动 useTurbine,useThree 不用碰。

03 3D 场景

  • 渲染器开 alpha + localClippingEnabled------削切动画的前提,很多人做"切开外壳"失败就漏这行
  • 模型 3 个 GLB(Draco 压缩):equipment(9 个零件)、skeleton(拆出颜色/线框两个外壳)、plane(地面)
  • getObjectByName 按建模命名取对象,省硬编码
  • 渲染循环用 renderMixins Map 挂自定义函数,可插拔

04 交互:Raycaster + 双层高亮

  • 点击 → Raycaster 拾取 → OutlinePass 描边
  • 悬浮 → 自定义 hexPass 改 material.emissive 自发光

两种技术路线,对外统一 selectedObjects 接口------状态切换收敛成 setter,是组件化交互最优雅的写法。

05 动画

  • 平面削切:THREE.PlaneclippingPlanes,TWEEN 动画化 constant 实现"切开外壳"
  • 拆解:零件坐标集中配置,从 COMPOSE 插值到 DECOMPOSE,用 TWEEN chain() 串序列(不用 setTimeout)
  • 标签:loadCSS2DByVue 把 Vue 组件渲染成 DOM 包成 CSS2DObject,复用模板/样式/事件

06 数据与图表

  • 动态数据用 mockjs,静态统计硬编码
  • ECharts 按需引入 + 封装 useEcharts,7 个面板不重复造轮子
  • 详情面板 computed(() => CONFIG[props.name]) 数据驱动切换

07 性能

  • autofit.js 1920×1080 等比缩放
  • 字体分包 + imagemin 压缩 + manualChunks 依赖分包,全指向首屏速度
  • 产物输出 docs/ + base:'./',GitHub Pages 零成本托管

08 三个工程细节

  1. 动画用 chain 不用 setTimeout------可控、可取消
  2. 卸载时 geometry/material.dispose()------不释放 GPU 内存会越跑越卡
  3. selectedObjects setter 即状态机------调用方不用管内部实现