返回笔记列表
01 · NOTES / WebGIS 开发

第 02 节 · 底图与瓦片源

2026 年 9 月 1 日

第 02 节 · 底图与瓦片源

📌 版本信息:Leaflet 1.9.4 / leaflet-providers 2.x(2026-08-29 核对) 📚 来源:leaflet-providers 预览页(上百种底图在线试) | 天地图 API 文档 | 本地 resources/05-leaflet/leaflet-providers/ 🎯 解决"底图从哪来、怎么换、怎么合规"三个问题。

一、这一节的目标

  1. 精通 TileLayer 的完整参数(URL 模板/子域/缩放范围/attribution)
  2. 掌握 providers 插件:一行换百种底图
  3. 掌握天地图接入(国内合规首选:分层 + key)
  4. 理解"底图 + 注记层"的叠加模型

二、TileLayer 参数全解

L.tileLayer(urlTemplate, options).addTo(map);

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  maxZoom: 19,             // 该源支持的最大级别(超了会 404——Leaflet 不再请求新瓦片)
  minZoom: 0,
  subdomains: 'abc',       // {s} 占位符的候选值:轮换子域规避浏览器同域并发限制(6 连接/域)
  attribution: '© OpenStreetMap',   // 版权(义务)
  opacity: 1,              // 透明度(叠加层常用 0.5~0.7)
  className: 'my-tiles',   // 挂 CSS 类(滤镜做暗色底图:filter: invert(1) hue-rotate(180deg))
  crossOrigin: true,       // 需要 canvas 读像素(截图/分析)时必须
  errorTileUrl: '占位图URL',  // 404 瓦片的替身
  keepBuffer: 2,           // 视口外保留几圈旧瓦片(拖动不平滑就调大它)
  updateWhenIdle: false,   // 移动端:拖动中是否加载(桌面默认 true)
  noWrap: false,           // 世界是否水平循环(经度 ±180 续接)
  bounds: [[..],[..]],     // 只在该范围加载(局部图层省流量)
});

💡 暗色底图的免费技巧className: 'dark-tiles' + .dark-tiles { filter: invert(1) hue-rotate(180deg) brightness(.9) }——把亮色 OSM 一键变暗色(大屏项目快速方案,正式项目用第 08 模块的矢量样式)。


三、providers 插件:一行换百种底图

<script src="https://unpkg.com/leaflet-providers@2.0.0/leaflet-providers_2.js"></script>
// 装插件后 L.tileLayer.provider('名字') 一行搞定(内置 URL/attribution)
L.tileLayer.provider('CartoDB.Positron').addTo(map);     // 浅灰简约
L.tileLayer.provider('CartoDB.DarkMatter').addTo(map);   // 暗色
L.tileLayer.provider('Esri.WorldImagery').addTo(map);    // 卫星影像
L.tileLayer.provider('Stadia.StamenTerrain', { key: '...' }) // 地形(部分需 key)
// 全目录见官方预览页;含高德/ogle 系(部分在国内不可用或需 key,预览页可筛)

注意:providers 只是"URL 收藏夹"——合规性要自己把关(商用配额、国内可访问性)。国内生产环境底图三选一:天地图(官方合规)/ 高德(体验好)/ 自建瓦片(可控,模块 14)。


四、天地图接入(国内合规标准流程)

const KEY = '你的key';   // lbs.tianditu.gov.cn 注册申请(免费,有配额)

// 天地图是"分层服务":底图与注记是两个服务,要叠两层!
const base = L.tileLayer(
  `https://t{s}.tianditu.gov.cn/vec_w/wmts?layer=vec&style=default&tilematrixset=w&Service=WMTS&Request=GetTile&Version=1.0.0&Format=tiles&TileMatrix={z}&TileRow={y}&TileCol={x}&tk=${KEY}`,
  { subdomains: ['0','1','2','3','4','5','6','7'], maxZoom: 18 }
);
const labels = L.tileLayer(
  `https://t{s}.tianditu.gov.cn/cva_w/wmts?layer=cva&style=default&tilematrixset=w&Service=WMTS&Request=GetTile&Version=1.0.0&Format=tiles&TileMatrix={z}&TileRow={y}&TileCol={x}&tk=${KEY}`,
  { subdomains: ['0','1','2','3','4','5','6','7'], maxZoom: 18 }
);
base.addTo(map);
labels.addTo(map);          // 注记层叠在底图上(没有它地图上没有文字!)
// 影像版:底图 img_w + 注记 cia_w;地形版 ter_w

第一次接天地图必踩的三坑:①忘了叠注记层(地图没字);②key 没配域名白名单(403);③用 w(球面墨卡托)服务却当 4326 数据对(坐标系口径,模块 04)。


五、动手跟练:02 · 多底图对比页

配套文件:05-leaflet/examples/02-多底图对比页.html

步骤:

  1. 一个页面四宫格或切换按钮:OSM / CartoDB 浅色 / Esri 卫星 / 天地图(vec+cva 叠加)四源同屏对比
  2. 完成 6 个 TODO:用 providers 插件换三种底图、天地图双层接入(自己填 key)、暗色滤镜实验(className + filter)、透明度滑块(opacity)、分层显隐(底图去/注记留——注记可单独存在)、subdomains 实验看 Network 的域名轮换
  3. 建一张"底图速查卡"(页面底部):每个源的名字/级别范围/是否需 key/合规场景

通关标准:

  • 四种底图切换流畅,天地图出字
  • 能背出 TileLayer 的 6 个常用参数
  • 能说出"国内生产底图三选一"及理由

六、自测题

  1. {s}{r} 占位符各是什么?
  2. 为什么 TileLayer 的 maxZoom 要与数据源匹配?
  3. 天地图底图与注记的关系?
  4. keepBuffer 调大解决什么问题?
  5. 暗色底图的快速方案?

参考答案

  1. {s}=子域轮换(破并发限制);{r}=retina 高清占位(源支持 @2x 时用)。
  2. 超出源能力的级别会持续 404;设对后 Leaflet 用放大算法兜底。
  3. 两个独立服务层:底图(vec/img/ter)+ 注记(cva/cia/cta),前端叠加成完整地图。
  4. 拖动时多保留视口外的旧瓦片,来回拖不闪白。
  5. 亮色源 + CSS filter invert+hue-rotate(className 方案);正式方案是矢量样式(模块 08)。

七、下一步

底图齐了 → 第 03 节:标记与图标,往地图上放"你的东西"。