提示词
使用Three.js和heatmap.js库创建3D热力图效果,通过ShaderMaterial将热力图数据转换为3D高度可视化。
效果拆解
| 效果 |
实现方式 |
| 热力图生成 |
使用heatmap.js生成2D热力图 |
| 纹理转换 |
将热力图Canvas转换为Three.js纹理 |
| 高度映射 |
通过着色器将热力值映射为高度 |
| 颜色显示 |
根据高度值显示对应颜色 |
| 透明度控制 |
根据高度值调整透明度 |
| 参数调节 |
使用GUI控制高度比例 |
核心技术点
1. 热力图生成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const getRandom = (max, min) => Math.round((Math.random() * (max - min + 1) + min) * 10) / 10
var heatmap = h337.create({
container: document.createElement('div'),
width: 256,
height: 256,
blur: '0.8',
radius: 10
});
var i = 0, max = 10, data = [];
while (i < 2000) {
data.push({ x: getRandom(1, 256), y: getRandom(1, 256), value: getRandom(1, 6) });
i++;
}
heatmap.setData({
max: max,
data: data
});
2. 纹理创建
const texture = new THREE.CanvasTexture(heatmap._renderer.canvas);
3. 着色器材质
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
const geometry = new THREE.PlaneGeometry(50, 50, 1000, 1000);
geometry.rotateX(-Math.PI * 0.5);
const material = new THREE.ShaderMaterial({
uniforms: {
heightMap: { value: texture },
heightRatio: { value: 5 }
},
vertexShader: `
uniform sampler2D heightMap;
uniform float heightRatio;
varying vec2 vUv;
varying float hValue;
varying vec3 cl;
void main() {
vUv = uv;
vec3 pos = position;
cl = texture2D(heightMap, vUv).rgb;
hValue = texture2D(heightMap, vUv).r;
pos.y = hValue * heightRatio;
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos,1.0);
}`,
fragmentShader: `
varying float hValue;
varying vec3 cl;
void main() {
float v = abs(hValue - 1.);
gl_FragColor = vec4(cl, .8 - v * v) ;
}`,
transparent: true,
})
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
4. GUI控制
new gui.add(mesh.material.uniforms.heightRatio, "value", 1, 15).name("heightRatio")
调试技巧
- 高度比例:调整heightRatio参数改变3D高度
- 热力点数量:修改循环次数控制热力点密度
- 热力点强度:调整value参数改变热力点强度
- 网格密度:调整PlaneGeometry的分段数获得更精细的效果
- 透明度范围:修改fragmentShader中的透明度计算公式
扩展思路
- 动态数据:实现热力图数据的实时更新
- 交互效果:鼠标悬停显示具体数值
- 多层数据:叠加多个热力图层
- 时间序列:实现热力图随时间变化的效果
- 3D交互:添加点击选择和缩放功能
- 数据导入:支持从外部文件导入热力图数据
💬 评论区
评论功能即将上线,敬请期待!