如何在客户端通过Mapbox GL JS使用Mapbox Terrain RGB制作淹没图
Mapbox GL JS 基于Terrain-RGB高程数据实现洪水淹没图教程
核心实现逻辑
Terrain-RGB栅格瓦片的每个像素通过RGB三个通道存储高程信息,解码公式为:
高程值(单位:米) = -10000 + (R * 256² + G * 256 + B) * 0.1
淹没效果的核心逻辑为:预设一个水位阈值,所有高程值低于等于该阈值的像素,渲染为指定的淹没效果色,高于阈值的像素保持透明。
分步实现代码
1. 加载Terrain-RGB数据源
在地图load事件回调中添加高程数据源,替换为你自己的瓦片请求地址模板即可:
map.on('load', () => { // 添加Terrain-RGB栅格数据源 map.addSource('terrain-rgb-source', { type: 'raster', tiles: ['你的Terrain-RGB瓦片地址模板'], tileSize: 256, maxzoom: 15 }); // 后续图层添加逻辑放这里 });
2. 添加淹没效果图层
推荐两种实现方式,可按需选择:
方式1:基于Mapbox内置表达式实现(无需写WebGL,上手简单)
直接通过raster系列表达式在图层配置中完成解码和渲染逻辑,代码量最小:
map.addLayer({ id: 'flood-layer', type: 'raster', source: 'terrain-rgb-source', paint: { 'raster-color': [ 'case', // 解码高程并和水位阈值对比,这里阈值设置为5米,可自行修改 ['<=', ['+', -10000, ['*', ['+', ['*', ['*', ['raster-value', 0], 256], 256], ['*', ['raster-value', 1], 256], ['raster-value', 2]], 0.1]], 5 ], // 低于阈值渲染为半透明蓝色 'rgba(0, 130, 210, 0.6)', // 高于阈值透明 'rgba(0,0,0,0)' ] } });
方式2:自定义WebGL图层实现(性能更高,可自定义效果)
如果需要更复杂的渲染效果(比如淹没边界渐变、动态水位动画),可以用自定义图层直接操作着色器:
const floodCustomLayer = { id: 'flood-custom-layer', type: 'custom', onAdd: function (map, gl) { // 顶点着色器:透传坐标 const vertexSource = ` attribute vec2 a_position; void main() { gl_Position = vec4(a_position, 0.0, 1.0); } `; // 片元着色器:解码高程+渲染淹没效果 const fragmentSource = ` precision mediump float; uniform sampler2D u_terrain_texture; uniform float u_flood_level; uniform vec2 u_screen_size; void main() { vec2 uv = gl_FragCoord.xy / u_screen_size; vec4 pixel = texture2D(u_terrain_texture, uv); float height = -10000.0 + (pixel.r * 65536.0 + pixel.g * 256.0 + pixel.b) * 0.1; // 可自行调整渲染逻辑,比如加渐变过渡效果 if (height <= u_flood_level) { gl_FragColor = vec4(0.0, 0.51, 0.82, 0.6); } else { gl_FragColor = vec4(0.0); } } `; // 编译着色器、创建程序、绑定缓冲区的常规WebGL逻辑此处省略,可直接套用WebGL自定义图层模板 // 存储程序、uniform位置等属性供render方法调用 this.program = createProgram(gl, vertexSource, fragmentSource); this.floodLevelLoc = gl.getUniformLocation(this.program, 'u_flood_level'); }, render: function (gl, matrix) { gl.useProgram(this.program); // 传入动态水位值,这里设置为5米,可绑定滑动条动态修改 gl.uniform1f(this.floodLevelLoc, 5); // 绑定纹理、绘制缓冲区的逻辑此处省略 } }; // 添加自定义图层到地图 map.addLayer(floodCustomLayer);
3. 交互扩展
可以添加一个滑块控件,动态修改水位阈值参数,即可实现水位升降的动态淹没动画效果。
注意事项
- Terrain-RGB高程值单位为米,设置水位阈值时需统一单位避免计算偏差
- 高程瓦片最高精度到15级,超过15级的区域会自动拉伸已有瓦片,精度可满足绝大多数场景需求
- 如果需要更平滑的淹没边界,可以在片元着色器中去掉硬判断,改用平滑插值计算透明度,视觉效果会更自然
内容的提问来源于stack exchange,提问作者sgm
相关产品推荐
相关产品推荐

