经纬志
首页 / 实战手册 / 数据加载

WMTS 的 TileMatrix 标识从 0 开始,瓦片整体错一层

先看结论

图层能显示,但比例尺总比底图大一级,设施点位与影像对不上。

最后验证 2026-11-03 · 多技术栈 · 更新 2026-10-29 · 引用本文

现象

叠加 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 张」, 两边差一级,所有请求都发生平移。

排查过程

  1. 打开 GetCapabilities,找 <TileMatrix> 的 Identifier 与 ScaleDenominator。
  2. 算 0 级的分辨率:ScaleDenominator × 0.00028 米/像素,再与经纬度换算比对。
  3. 把前端请求的 z 与 Capabilities 里的标识逐个对照,看是否整体偏移。
  4. 用 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.0TileMatrix 标识符为字符串,不隐含层级
GeoServer2.20 及以上默认 EPSG:4326:0 起,MatrixWidth=2
OpenLayers9.xWMTSTileGrid 需显式给 resolutions
引用本文

经纬志(2026)。《WMTS 的 TileMatrix 标识从 0 开始,瓦片整体错一层》。https://www.jingweizhi.com/cookbook/wmts-tilematrix-offset.html(访问日期 2026-11-03)。