有趣的3D图表水球:从 ECharts 到 RayChart 的升维打击
在数据可视化大屏中,"水球图"(Liquid Fill Chart)绝对是展示百分比数据(如CPU使用率、完成度、剩余电量)的颜值担当。
大家最熟悉的莫过于 ECharts 的 echarts-liquidfill 插件。它简单、好用,但在这个"卷"视觉的时代,传统的 2D 扁平水球有时显得不够"震撼"。
今天我们来聊聊一个有趣的话题:如何用 RayChart 手搓一个真实的 3D 水球,并对比它与 ECharts 水球的区别。 raychart体验地址:https://chart3js.netlify.app

1. 传统的 2D 做法:ECharts LiquidFill
ECharts 的水球本质上是 2D Canvas/SVG 绘图。
原理
它的"波浪"并不是真的流体,而是通过数学公式(通常是正弦函数 y = A * sin(Bx + C) + D)在 2D 平面上绘制出的闭合路径。通过不断改变相位(Offset),让曲线平移,从而产生"波动"的视觉错觉。
特点
- 优点 :
- 性能极佳:几乎不占用 GPU 资源。
- 兼容性好:甚至可以在不支持 WebGL 的环境运行。
- 配置简单:几行配置就能搞定。
- 缺点 :
- 扁平:没有厚度,没有光影。
- 质感单一:虽然可以加渐变色,但无法表现出水的折射、玻璃的通透感。
2. 进阶的 3D 做法:RayChart 硬核实现
为了追求"透亮"、"像真水一样"的效果,我们必须引入 WebGL 和 PBR(基于物理的渲染)。
在我的开源项目 RayChart 中,我实现了一个 Liquid3D 组件。下面来看看它是如何"骗"过你的眼睛的。

核心构成
一个真实的 3D 水球通常由三部分组成:
- 玻璃外壳:一个透明的球体容器。
- 液体主体:球体内部被截断的下半部分。
- 液体表面:一个随波浪起伏的顶盖。
技术实现细节
A. 玻璃外壳 (The Glass Shell)
ECharts 很难做出的效果就是"玻璃感"。在 RayChart (基于 Three.js) 中,我们使用 MeshPhysicalMaterial,并开启 transmission(透光率)属性。
typescript
const shellMaterial = new THREE.MeshPhysicalMaterial({
color: 0xffffff,
transmission: 0.9, // 90% 透光,像玻璃一样
roughness: 0, // 极其光滑
ior: 1.5, // 折射率,模拟玻璃/水晶
thickness: 0.5, // 厚度,产生真实的折射效果
transparent: true
});
这让背景能够透过球体产生扭曲,质感瞬间拉满。
B. 液体主体:着色器里的"裁剪术"
液体本身其实也是一个球体(SphereGeometry),但我们需要根据水位把它"切"开。
普通的 clippingPlanes 切出来是平的,没有波浪。所以我们需要写一点 Shader(着色器)。
秘籍: 使用 onBeforeCompile 修改标准材质,在 Fragment Shader 中加入 discard 逻辑。
glsl
// GLSL 片段着色器伪代码
float h = getWaveHeight(vWorldPosition.x, vWorldPosition.z); // 计算波浪高度
// 如果当前像素的高度 > 水位 + 波浪高度,就丢弃(不渲染)
if (vWorldPosition.y > uLevelY + h) discard;
这样,原本完整的球体就被"切"出了一个起伏的边缘。
C. 液体表面:动态波浪
被切掉的顶部不能空着,需要盖一个"盖子"。这个盖子是一个高密度的 PlaneGeometry。
难点: 盖子的波动必须和球体的切口严丝合缝,否则会漏水。
解决方案:
- 几何同步:表面使用与主体完全相同的波浪公式(正弦波叠加)。
- 圆形遮罩:因为 Plane 是方形的,我们需要在 Shader 里把超出球体半径的部分裁掉。
glsl
// Vertex Shader: 让顶点随波浪起伏
vec3 pos = position;
float waveH = getWaveHeight(worldPos.x, worldPos.z);
pos.y += waveH; // 顶点置换
// Fragment Shader: 切成圆形
if (length(vUv - 0.5) * 2.0 > 1.0) discard;
3. 终极对比:ECharts vs RayChart
| 维度 | ECharts LiquidFill | RayChart Liquid3D |
|---|---|---|
| 渲染引擎 | Canvas / SVG | WebGL (Three.js) |
| 视觉维度 | 2D 平面 | 3D 空间 |
| 质感 | 色块、渐变、扁平阴影 | 折射、反射、高光、环境光遮蔽 |
| 交互 | 鼠标悬浮高亮 | 360度旋转、缩放、甚至可以晃动液体 |
| 性能开销 | ⭐ (极低) | ⭐⭐⭐ (中高,依赖 GPU) |
| 适用场景 | 普通报表、H5 页面、移动端 | 大屏可视化、数字孪生、高逼格演示 |
4. 总结
- 如果你需要一个快速加载、兼容性强 的进度展示,ECharts 依然是首选。
- 如果你在做酷炫的数据大屏 ,想要那种"看起来很贵"的效果,RayChart 的 3D 水球绝对值得一试。
RayChart 项目正在探索更多这样的 3D 图表组件,希望能把 WebGL 的门槛降下来,让大家都能轻松用上"电影级"的图表。
觉得有趣的话,欢迎点赞收藏!