WMTS 的 TileMatrix 标识从 0 开始,瓦片整体错一层
图层能显示,但比例尺总比底图大一级,设施点位与影像对不上。
现象
叠加 GeoServer 发布的 WMTS 图层,缩放级别 14 时, 叠加层显示的是 15 级的细节,边界比底图粗一圈; 缩到地图最小时,叠加层是空白,网络面板里该请求返回 200 的空白 PNG。
请求 URL 中的 TILEMATRIX=EPSG:4326:14,
而 Capabilities 里实际定义的标识是 EPSG:4326:0 到 EPSG:4326:21,
但 0 级并不是全球一张图,而是 1:559082264 的层级,
与 Leaflet 认为的「0 级 = 全球一张」不一致。
原因
WMTS 规范里 TileMatrix 的标识符只是一个字符串,
与数字层级没有强制对应关系。GeoServer 默认按
EPSG:4326:{n} 生成,n 从 0 开始,
但 0 级的分辨率是 0.703125 度/像素,对应 2 张 256 像素瓦片覆盖全球,
不是 1 张。
Leaflet 和 OpenLayers 的默认瓦片网格假设「z=0 时全球 1 张」, 两边差一级,所有请求都发生平移。
排查过程
- 打开
GetCapabilities,找<TileMatrix>的Identifier与ScaleDenominator。 - 算 0 级的分辨率:
ScaleDenominator × 0.00028米/像素,再与经纬度换算比对。 - 把前端请求的 z 与 Capabilities 里的标识逐个对照,看是否整体偏移。
- 用
TILEMATRIX=EPSG:4326:0手工请求一张,确认返回的是 2×1 还是 1×1 网格。
<TileMatrix>
<ows:Identifier>EPSG:4326:0</ows:Identifier>
<ScaleDenominator>279541132.0143589</ScaleDenominator>
<TopLeftCorner>90 -180</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>2</MatrixWidth>
<MatrixHeight>1</MatrixHeight>
</TileMatrix>
解决方案
让前端网格与 Capabilities 对齐。GeoServer 可以在图层设置里把
TileMatrixSet 的起始级别改成 1,也可以在前端补偿。
// Leaflet:自定义 WMTS 网格,标识符与 z 解耦
const matrixIds = [];
for (let z = 0; z <= 21; z++) matrixIds[z] = 'EPSG:4326:' + z;
L.tileLayer('http://localhost:8080/geoserver/gwc/service/wmts?SERVICE=WMTS&REQUEST=GetTile' +
'&VERSION=1.0.0&LAYER=gis:districts&STYLE=&FORMAT=image/png' +
'&TILEMATRIXSET=EPSG:4326&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}', {
tileSize: 256,
tms: false,
maxZoom: 21,
minZoom: 0,
zoomOffset: 0
}).addTo(map);
OpenLayers 的做法是把 tileGrid 的 resolutions 从 Capabilities 抄下来,
不要用 createXYZ() 的默认值。
import WMTS from 'ol/source/WMTS';
import WMTSTileGrid from 'ol/tilegrid/WMTS';
const grid = new WMTSTileGrid({
origin: [-180, 90],
resolutions: [0.703125, 0.3515625, 0.17578125, 0.087890625],
matrixIds: ['EPSG:4326:0', 'EPSG:4326:1', 'EPSG:4326:2', 'EPSG:4326:3'],
tileSize: 256
});
验证
同一缩放级别下,叠加层与底图的道路应完全重合; 缩到最小级别时叠加层不再是空白,请求 URL 中的 TILEMATRIX 与 Capabilities 标识一致。
// 网格一致性校验:0 级应为 2×1 张瓦片
const mw = 2, mh = 1;
console.assert(mw === 2 && mh === 1, '0 级网格仍是 1×1,说明仍在用 XYZ 假设');
适用版本
| 组件 | 版本 | 说明 |
|---|---|---|
| WMTS 规范 | 1.0.0 | TileMatrix 标识符为字符串,不隐含层级 |
| GeoServer | 2.20 及以上 | 默认 EPSG:4326:0 起,MatrixWidth=2 |
| OpenLayers | 9.x | WMTSTileGrid 需显式给 resolutions |
经纬志(2026)。《WMTS 的 TileMatrix 标识从 0 开始,瓦片整体错一层》。https://www.jingweizhi.com/cookbook/wmts-tilematrix-offset.html(访问日期 2026-11-03)。