在MapLibre GL JS中如何在拉伸多边形上叠加不重复图片?
解决MapLibre拉伸多边形(fill-extrusion)图片无重复叠加问题
方案一:使用自定义着色器(推荐)
fill-extrusion-pattern的重复特性是内置的,要实现单张图片无重复覆盖,最可靠的方式是通过自定义着色器直接控制纹理采样逻辑:
- 加载并注册图片纹理
先将需要叠加的图片加载到MapLibre的纹理集中:
map.loadImage('/path/to/your-image.png', (error, image) => { if (error) throw error; // 注册为普通纹理(非SDF格式) map.addImage('extrusion-texture', image, { sdf: false }); });
- 创建带自定义着色器的fill-extrusion图层
通过自定义片段着色器,基于多边形的边界范围计算纹理坐标,让图片完整覆盖拉伸面:
// 提前计算目标多边形的经纬度包围盒(minX, minY, maxX, maxY) // 可通过turf.bbox()工具库快速获取复杂多边形的边界 const polygonBounds = [116.3, 39.9, 116.4, 40.0]; // 示例边界 map.addLayer({ id: 'textured-extrusion', type: 'fill-extrusion', source: 'your-polygon-source', // 替换为你的多边形数据源ID paint: { 'fill-extrusion-height': 150, 'fill-extrusion-base': 0, 'fill-extrusion-opacity': 1 }, shader: { extensions: ['#extension GL_OES_standard_derivatives : enable'], // 自定义片段着色器 frag: ` precision highp float; uniform sampler2D extrusion_texture; uniform vec4 polygon_bounds; varying vec2 v_pos; void main() { // 将顶点位置映射为0-1范围的纹理坐标 vec2 uv = (v_pos - polygon_bounds.xy) / (polygon_bounds.zw - polygon_bounds.xy); // 采样纹理,确保图片无重复 vec4 texColor = texture2D(extrusion_texture, uv); // 混合纹理颜色与基础颜色 gl_FragColor = texColor * gl_FragColor; } `, // 传入uniform变量 uniforms: { extrusion_texture: { type: 'sampler2D', value: 'extrusion-texture' }, polygon_bounds: { type: 'vec4', value: polygonBounds } } } });
关键说明:
- 着色器中通过将顶点坐标映射到0-1区间,确保图片完整覆盖整个拉伸多边形,避免重复平铺。
- 复杂多边形的边界可借助
turf.js的bbox()方法快速计算。
方案二:平面Raster图层叠加(仅适用于简单场景)
如果你的拉伸多边形是规则矩形且视角固定,可以尝试用raster图层叠加在fill-extrusion上方,但这种方法在3D视角旋转时会出现错位,仅适合特定场景:
map.addLayer({ id: 'overlay-raster', type: 'raster', source: { type: 'image', url: '/path/to/your-image.png', coordinates: [ [polygonBounds[0], polygonBounds[3]], // 左上 [polygonBounds[2], polygonBounds[3]], // 右上 [polygonBounds[2], polygonBounds[1]], // 右下 [polygonBounds[0], polygonBounds[1]] // 左下 ] }, paint: { 'raster-opacity': 1 }, // 将图层置于fill-extrusion之上 beforeId: 'top-layer-id' });
内容的提问来源于stack exchange,提问作者Renjith
相关产品推荐
相关产品推荐

