【附源码,附两款可视化大屏】Three.js中的地图精确贴图与热力图实现解析

🎉实现效果图

项目地址

如果你觉得不错的话,帮我点一个小小的star

访问需要魔法。👉点击访问👈

在线预览

👉点击访问效果图2👈

精确贴图实现

精确贴图是将2D纹理准确地映射到3D几何体表面的技术。在我们的项目中,通过以下步骤实现了精确贴图:

1. UV坐标计算

为了确保纹理能够正确地映射到几何体上,我们需要计算每个顶点的UV坐标:

javascript 复制代码
useLayoutEffect(() => {
  const { geometry } = meshRef.current;
  const pos = geometry.attributes.position;
  const width = bbox.max.x - bbox.min.x;
  const height = bbox.max.y - bbox.min.y;

  const uv: number[] = [];
  let x = 0, y = 0, u = 0, v = 0;
  for (let i = 0; i < pos.count; i++) {
    x = pos.getX(i);
    y = pos.getY(i);
    u = (x - bbox.min.x) / width;
    v = (y - bbox.min.y) / height;
    uv.push(u, v);
  }
  geometry.setAttribute("uv", new Float32BufferAttribute(uv, 2));
});

这段代码通过遍历几何体的所有顶点,根据包围盒(bbox)计算出每个顶点对应的UV坐标,确保纹理能按照正确的比例映射到几何体表面。

2. 纹理加载与配置

在项目中,我们使用 useTexture钩子加载纹理,并进行必要的配置:

javascript 复制代码
const [texture1, texture2, texture3] = useTexture(
  [textureMap, scNormalMap, scDisplacementMap],
  (tex) =>
    tex.forEach((el) => {
      el.wrapS = el.wrapT = RepeatWrapping;
    })
);

3. 材质应用

最后,我们将纹理应用到材质上:

jsx 复制代码
<meshStandardMaterial
  map={texture1}
  normalMap={texture2}
  displacementMap={texture3}
  metalness={0.2}
  roughness={0.5}
  side={DoubleSide}
/>

通过这种方式,我们可以为3D对象添加漫反射贴图、法线贴图和置换贴图,从而创造出更加真实和细节丰富的视觉效果。

热力图实现

热力图是一种用颜色编码来表示数据密度或强度的可视化技术。在我们的项目中,使用了 heatmap.js库来实现热力图功能。

1. 热力图数据准备

首先,我们需要准备热力图的数据点:

javascript 复制代码
const points = data.features.map((el) => {
  const [x = 0, y = 0] =
    projection(el.geometry.coordinates as [number, number]) ?? [];
  return {
    x: Math.floor(x + size / 2),
    y: Math.floor(y + size / 2),
    value: el.properties.value,
  };
});

这些数据点包含了位置信息(x,y)和数值(value),用于生成热力图。

2. 热力图生成

使用 heatmap.js创建热力图:

javascript 复制代码
const heatmap = heatmapJs.create({
  container: heatmapContainer,
  gradient: {
    0.5: "#1fc2e1",
    0.6: "#24d560",
    0.7: "#9cd522",
    0.8: "#f1e12a",
    0.9: "#ffbf3a",
    1.0: "#ff0000",
  },
  blur: 1,
  radius: radius,
  maxOpacity: 1,
  width: size,
  height: size,
});
javascript 复制代码
const greymap = heatmapJs.create({
  container: heatmapContainer,
  gradient: {
    0.0: "black",
    1.0: "white",
  },
  radius: radius,
  maxOpacity: 1,
  width: size,
  height: size,
});

这里定义了颜色渐变,不同的数值范围对应不同的颜色,从而形成热力图的视觉效果。

3. 与Three.js集成

将生成的热力图作为纹理应用到Three.js的网格上:

javascript 复制代码
const texture = new CanvasTexture(heatmap._renderer.canvas);
texture.needsUpdate = true;

// 在着色器中使用该纹理
uniforms: {
  heatMap: { value: texture },
  // 其他uniforms...
}

通过这种方式,我们将2D热力图转换为可以在3D场景中使用的纹理。

4. 着色器实现

在片段着色器中使用热力图纹理:

glsl 复制代码
varying vec2 vUv;
uniform sampler2D heatMap;
uniform vec3 u_color;
uniform float u_opacity;

void main() {
    gl_FragColor = vec4(u_color, u_opacity) * texture2D(heatMap, vUv);
}

这样就完成了热力图在3D场景中的渲染。

相关推荐
木斯佳6 小时前
前端八股文面经大全:26届秋招滴滴校招前端一面面经-事件循环题解析
前端·状态模式
光影少年6 小时前
react状态管理都有哪些及优缺点和应用场景
前端·react.js·前端框架
saber_andlibert8 小时前
TCMalloc底层实现
java·前端·网络
逍遥德8 小时前
如何学编程之01.理论篇.如何通过阅读代码来提高自己的编程能力?
前端·后端·程序人生·重构·软件构建·代码规范
冻感糕人~8 小时前
【珍藏必备】ReAct框架实战指南:从零开始构建AI智能体,让大模型学会思考与行动
java·前端·人工智能·react.js·大模型·就业·大模型学习
程序员agions8 小时前
2026年,“配置工程师“终于死绝了
前端·程序人生
alice--小文子8 小时前
cursor-mcp工具使用
java·服务器·前端
晚霞的不甘8 小时前
揭秘 CANN 内存管理:如何让大模型在小设备上“轻装上阵”?
前端·数据库·经验分享·flutter·3d
小迷糊的学习记录8 小时前
0.1 + 0.2 不等于 0.3
前端·javascript·面试
梦帮科技9 小时前
Node.js配置生成器CLI工具开发实战
前端·人工智能·windows·前端框架·node.js·json