setTerrain 之后地面还是平的
按照文档加了地形源,倾斜视角后山脉毫无起伏,建筑也没有跟着贴到坡面上。
现象
map.setTerrain({ source: 'terrain', exaggeration: 1.5 }) 执行成功,
但画面没有高度变化。map.getTerrain() 返回对象,说明配置已被接受。
有时控制台报:
Error: Source "terrain" cannot be used as terrain because it is not a raster-dem source.
原因
| 原因 | 表现 |
|---|---|
源类型写成 raster | 直接报上述错误 |
encoding 与数据不匹配 | 不报错,地形几乎为 0 或出现巨大尖刺 |
DEM 瓦片 tileSize 写成 512 | 高程被错误插值,起伏很浅 |
maxzoom 小于当前缩放 | 远处有起伏,近处反而平坦 |
| 视角是垂直俯视 | 视觉上看不出高度差 |
encoding 有两个取值:terrarium 与 mapbox。
两者解码公式不同,用错时高程会被算成几十米到几千米的偏差。
排查过程
先确认源类型和编码,再确认是否真的取到了瓦片:
var src = map.getSource('terrain');
console.log('源类型', src.type);
console.log('地形配置', map.getTerrain());
map.on('error', function (e) { console.error(e.error && e.error.message); });
用瓦片地址单独下载一张 DEM,检查 PNG 的尺寸与像素值。
256×256 对应 tileSize: 256,512×512 对应 512,不能凭经验填。
解决方案
明确声明 raster-dem、编码与瓦片尺寸,并给足最大级别:
map.addSource('terrain', {
type: 'raster-dem',
tiles: ['https://dem.example.cn/{z}/{x}/{y}.png'],
encoding: 'terrarium', // 按数据生产方确认
tileSize: 256,
minzoom: 0,
maxzoom: 12,
attribution: 'DEM © Example'
});
map.setTerrain({ source: 'terrain', exaggeration: 1.5 });
地形生效后,倾斜视角才能看出来。给一个初始俯仰角,避免用户以为没加载:
map.setPitch(55);
map.setBearing(20);
建筑需要贴地时,给 fill-extrusion 图层打开垂直贴地:
map.addLayer({
id: 'buildings-3d',
type: 'fill-extrusion',
source: 'buildings',
paint: {
'fill-extrusion-height': ['get', 'height'],
'fill-extrusion-base': ['get', 'min_height'],
'fill-extrusion-color': '#c9d3dd',
'fill-extrusion-opacity': 0.9
}
});
验证
把 exaggeration 从 1 调到 2,同一机位下山体轮廓明显变化。
在地形起伏大的区域,建筑底部与坡面贴合,不出现悬空。
map.getTerrain() 的 source 与设置一致。
先确认编码:同一份 DEM 用错 encoding,画面会变成
“整体像平地”或“到处是尖刺”两种极端,都不会报错。
向数据提供方确认编码,比反复调 exaggeration 有效。
经纬志(2026)。《setTerrain 之后地面还是平的》。https://www.jingweizhi.com/cookbook/maplibre-terrain-not-work.html(访问日期 2026-11-03)。