Skip to content

瓦片图层与网格系统

本文档涵盖 Leaflet 的瓦片图层架构,包括 GridLayer 基类和 TileLayer 实现。它解释了瓦片坐标系统、URL 模板、瓦片加载机制和缓存策略,这些功能共同实现了瓦片地图数据的高效显示。

关于其他图层类型的信息,请参阅 矢量图层。关于渲染系统详情,请参阅 矢量渲染系统

架构概览

Leaflet 的瓦片系统采用双层架构,其中 GridLayer 提供基础的网格管理功能,TileLayer 实现从瓦片服务器加载图片瓦片的具体逻辑。

SVG
100%

GridLayer 职责:

  • 通过 _tileCoordsToKey()_keyToTileCoords() 进行瓦片坐标计算和网格管理
  • 通过 _addTile()_removeTile()_tileReady() 管理瓦片生命周期
  • 使用 _updateLevels()_setView()_clampZoom() 处理缩放级别
  • 通过 _pruneTiles()_retainParent()_retainChildren() 实现瓦片缓存和修剪

TileLayer 职责:

  • 使用 getTileUrl()Util.template() 处理 URL 模板
  • createTile() 中创建图片瓦片并带有异步加载回调
  • 通过 _getSubdomain() 实现子域轮换,通过 Browser.retina 支持 Retina 显示屏
  • _tileOnError() 中进行错误处理,并提供 errorTileUrl 回退机制

GridLayer 基类

GridLayer 作为 Leaflet 中所有瓦片图层的基础。它管理缩放级别的层次结构,每个级别包含一个瓦片网格,使用 CSS transforms 进行定位。

核心数据结构

图表:GridLayer 内部状态结构

SVG
100%

_levels 对象将缩放级别映射到带有定位信息(originzoom)的 DOM 容器。_tiles 对象使用 _tileCoordsToKey(coords) 生成类似 '2048:1536:12' 的字符串键,这些键映射到包含 DOM 元素(el)、坐标信息(coords)和状态标志(currentloadedactiveretain)的瓦片对象。

瓦片坐标系统

GridLayer 使用标准的 Web Mercator 瓦片坐标系统,每个瓦片由 {x, y, z} 坐标标识:

  • z:缩放级别(0 = 整个世界在单个瓦片中)
  • x:列索引(从西到东)
  • y:行索引(从北到南)

图表:瓦片坐标到缓存键的映射

SVG
100%

坐标到键的转换在 _tileCoordsToKey() 中实现,它创建字符串键,而 _keyToTileCoords() 执行反向操作,通过解析键字符串并返回带有 z 属性的 Point

TileLayer 实现

TileLayer 扩展 GridLayer,提供使用 URL 模板从瓦片服务器加载图片瓦片的功能。

URL 模板系统

TileLayer 处理带有占位符替换的 URL 模板:

占位符描述来源示例
{z}缩放级别this._getZoomForUrl()12
{x}瓦片 X 坐标coords.x2048
{y}瓦片 Y 坐标coords.y 或反转1536
{s}子域this._getSubdomain(coords)a, b, c
{r}Retina 后缀Browser.retina ? '@2x' : ''@2x 或 ``
{-y}反转 Y 坐标_globalTileRange.max.y - coords.y用于 TMS
自定义任意选项键this.options[key]用户自定义

图表:URL 模板处理流程

SVG
100%

模板系统使用 Util.template(),它从数据对象中替换 {key} 占位符。可以通过图层选项添加自定义占位符,这些占位符将被自动包含。

瓦片创建和加载

TileLayer 实现 createTile() 方法来生成带有异步加载的 <img> 元素:

图表:瓦片创建和异步加载序列

SVG
100%

错误处理包括如果设置了 options.errorTileUrl,则回退到该 URL,错误通过 done 回调传递,触发 tileerror 事件。

瓦片加载生命周期

瓦片加载过程涉及坐标计算、瓦片创建和基于距视口中心距离的渐进式加载。

瓦片更新流程

图表:瓦片更新和加载流程

SVG
100%

瓦片使用 coords.distanceTo(tileCenter) 按距视口中心的距离排序,并按该顺序加载以优先显示可见内容。_update() 方法使用 DocumentFragment 批量进行 DOM 插入以提高性能。

瓦片修剪和保留

GridLayer 实现复杂的瓦片保留逻辑,以平衡内存使用和平滑的缩放过渡:

图表:瓦片金字塔保留策略

SVG
100%

这种基于金字塔的保留方式保持父瓦片(最多低 5 个缩放级别)和子瓦片(最多高 2 个缩放级别),以实现平滑的缩放过渡。保留基于瓦片的 "active" 状态,该状态在瓦片完成淡入动画后设置。

缩放级别管理

GridLayer 与 Map 协调以建立缩放约束并管理多分辨率瓦片显示。

缩放边界集成

图表:带有图层的 Map 缩放边界计算

SVG
100%

GridLayers 通过 _addZoomLimit() 向地图注册自身,这会更新 _zoomBoundLayers 并触发 _updateZoomLevels()。地图的有效缩放边界将显式的 options.minZoom/maxZoom(如果设置)与所有图层缩放边界的并集结合起来。当图层被移除时,_removeZoomLimit() 会相应更新边界。

原生缩放边界限制

minNativeZoommaxNativeZoom 选项控制瓦片源仅在特定缩放级别提供瓦片时的瓦片缩放级别限制:

图表:原生缩放边界的 _clampZoom() 逻辑

SVG
100%

例如,如果地图处于缩放级别 15 但设置了 maxNativeZoom: 12,GridLayer 将请求缩放级别 12 的瓦片,并通过 CSS transforms 将其放大 2³ = 8 倍。这在使用 map.getZoomScale(mapZoom, tileZoom)_setZoomTransform() 中计算。

性能考量

GridLayer 包含多项优化,以实现平滑的瓦片显示和高效的内存使用。

更新节流

图表:地图移动期间的瓦片更新节流

SVG
100%

updateWhenIdle 选项(在移动设备上默认 true,通过 Browser.mobile)决定是否在平移期间更新瓦片。当为 false 时,_onMove 处理程序被创建为 _onMoveEnd() 的节流版本,使用 options.updateInterval(默认 200ms)来限制连续地图移动期间的更新频率。

瓦片淡入动画

SVG
100%

平滑的淡入动画提高了感知性能,同时与瓦片修剪协调以优化内存使用。