前言

MapLibre 是一个开源的地图渲染工具集,能为Web、移动应用和桌面端提供高性能、高度可定制的地图渲染解决方案。MapLibre的核心是利用GPU进行硬件加速渲染,因此地图的缩放、平移和旋转等操作能保持在60fps,体验流畅顺滑。2020年底,Mapbox GL JS v2.0转向了专有许可证。为了维护一个完全免费、开源的地图库,社区从最后一个开源版本v1.13分叉(fork)出了MapLibre项目。因此,它与旧版Mapbox高度兼容,并在此基础上独立发展,持续增加新特性。我们可以对比一下MapLibre、Mapbox、Leaflet、OpenLayers。

对比项 MapLibre Mapbox Leaflet / OpenLayers
许可证 开源 (BSD) 商业专有 开源
渲染方式 GPU加速 (WebGL),性能高 GPU加速 (WebGL),性能高 多为Canvas/SVG,性能较低
矢量瓦片 原生支持,体验好 原生支持,体验好 需插件支持,体验一般
样式定制 极其灵活,基于JSON规范 极其灵活,基于JSON规范 定制性较弱
商业使用 完全免费,无访问令牌 需付费,有访问令牌 完全免费
核心优势 自由、免费、高性能、社区驱动 生态完善、服务集成 轻量、插件多 (Leaflet) / 专业GIS功能 (OpenLayers)

1 总览

技能 适用场景
maplibre-tile-sources 选择地图数据的供给方式;在 GeoJSON 与瓦片之间做决策;配置底图;调试空白地图或缺少标注的问题
maplibre-pmtiles-patterns 无需瓦片服务器托管瓦片;静态部署或无服务器部署;从 MBTiles 转换;基于 OSM 或 GeoJSON 生成瓦片
maplibre-mapbox-migration 将现有 Mapbox GL JS 应用迁移至 MapLibre;评估 MapLibre 作为开源替代方案的可行性

2 maplibre-tile-sources.md


名称: maplibre-tile-sources
描述: 如何为 MapLibre GL JS 选择和配置数据源——渲染自己的数据(无需瓦片)、托管瓦片服务、无服务器 PMTiles、自托管瓦片服务器、瓦片模式、字形和精灵图。


MapLibre 瓦片数据源

MapLibre GL JS 本身不携带地图数据。你需要提供一个样式,其中引用数据源——即 MapLibre 获取并渲染的 URL 或内联数据。MapLibre 既能很好地支持包含 200 个地址的店铺定位地图,也能胜任城市交通图乃至全球底图——选择合适的数据源类型取决于地理范围与细节层级、更新频率、基础设施限制以及具体用例。

何时使用此技能

  • 搭建新的 MapLibre 地图并决定数据来源时
  • 在 GeoJSON、无服务器瓦片、托管服务、组合使用或自托管方案之间做抉择时
  • 配置字形(字体)和精灵图以使标注和图标正常渲染时
  • 调试空白地图或瓦片缺失问题时
  • 从 Mapbox 迁移,需要等效的瓦片数据源和样式设置时

样式与数据源的工作原理

样式(样式 JSON、样式文档或样式对象)是你传递给 MapLibre 的配置。它包含受 MapLibre 样式规范 约束的具体渲染规则,该规范在 MapLibre GL JS 和 MapLibre Native 中保持同步。

你可以使用来自服务商的样式 URL——该 URL 引用的样式包含数据源、图层、字形和精灵图。你也可以自己构建样式,逐一配置每一项。

一个样式包含三个主要部分:

  • 数据源 — 指向实际数据。每个数据源有 type 字段,以及内联数据或一个 URL。MapLibre 会根据视口变化请求瓦片或数据。同一个数据源可被多个图层使用(例如道路、水域和标注可全部来自同一个矢量 URL)。
  • 图层 — 有序列表,定义绘制内容与绘制方式。每个图层引用一个数据源(对于矢量瓦片还需指定 source-layer 名称),并指定绘制与布局属性。
  • 字形与精灵图 — 显示文字和图标所必需:指向字体 SDF 堆栈和图标精灵表单的 URL。缺失这些,标注和符号将无法显示。

数据源类型:

类型 描述
vector 矢量瓦片 — 二进制编码的几何与属性;是底图和数据叠加层的主要格式
raster 栅格瓦片影像 — 卫星照片、WMS/WMTS 图层
raster-dem 高程瓦片 — 用于地形渲染和山体阴影
geojson GeoJSON 数据 — 内联对象或 URL;无需瓦片服务器
image 单张地理参照图像 — 扫描地图、注释叠加层
video 地理参照视频

vectorraster 在底图和数据叠加层中最常见。geojson 非常适合小型数据集或无需切片的交互式数据。raster-dem 用于地形和山体阴影效果,以及科学可视化等新兴场景。imagevideo 数据源使用较少,但可将静态图像(如扫描地图、图表或叠加层)或地理参照视频作为地图图层。

GeoJSON 与直接数据源

许多场景下你并不需要瓦片服务。MapLibre 可以直接从内联 GeoJSON 对象或 GeoJSON 文件 URL 渲染点、线、面。整个数据集在浏览器中下载并解析;客户端渲染由 MapLibre 处理。

map.addSource('my-data', {
  type: 'geojson',
  data: '/path/to/data.geojson' // 或者内联 GeoJSON 对象
});
map.addLayer({
  id: 'my-layer',
  type: 'fill',
  source: 'my-data',
  paint: { 'fill-color': '#0080ff', 'fill-opacity': 0.5 }
});

GeoJSON 性能阈值

GeoJSON 每次加载都会下载整个文件。小规模时表现良好,随数据量增大性能可预测地下降:

范围 文件大小 / 要素数量 表现
理想区间 < 2 MB / < 5,000 个要素 即时加载,交互流畅
延迟区间 5–20 MB / 最多约 50,000 个要素 1–3 秒解析延迟;移动端可能吃力;通过简化几何与降低坐标精度优化
崩溃区间 > 50 MB / > 100,000 个要素 浏览器冻结或崩溃风险高;应改用矢量瓦片

GeoJSON 是无损的(精确坐标得以保留),并且能让你在客户端完全访问要素属性——非常适合交互式数据、动态更新,以及需要查询或修改要素而无需往返服务器的数据集。

如果数据集超过上述阈值,或者需要按缩放级别进行差异化渲染(低缩放级别下降低细节),则应考虑使用矢量瓦片。

其他格式与云原生生态

数据源的选择不仅受性能影响,还涉及数据类型、更新频率、访问模式以及更广泛的地理空间生态。许多格式(FlatGeobuf、GeoParquet、Cloud-Optimized GeoTIFF、KML、GPX 等)可通过插件和自定义协议在 MapLibre 中显示。云原生地理空间生态——专为 HTTP 范围请求和分布式存储设计的格式——正快速发展,对 web 地图日益重要。将有专门技能深入探讨;目前可参阅 awesome-maplibre 的地图渲染插件工具库 章节。

何时需要瓦片

矢量瓦片以紧凑的二进制格式仅加载当前视口可见的数据。在以下场景中使用它们:

  • 数据集超出 GeoJSON 的实用极限
  • 需要按缩放级别差异化渲染(不同缩放级别下展示不同细节)
  • 需要全球或区域参考图层,例如陆地与水域、道路、地名等(即底图数据)
  • 大规模应用中带宽效率至关重要

矢量瓦片 vs. 栅格瓦片

当你需要瓦片时,需在两种瓦片类型中选择:

矢量瓦片 将几何与要素属性编码为紧凑的二进制数据(Mapbox 矢量瓦片格式,或更新的 MapLibre Tile / MLT 格式)。MapLibre 在客户端渲染并应用样式:

  • 样式可修改而无需重新生成瓦片
  • 要素可查询(点击、悬停交互)
  • 文字在任何缩放比例或屏幕密度下均保持清晰
  • 文件体积远小于等效的栅格瓦片

栅格瓦片 是每个缩放级别下预渲染的图像(PNG、JPEG 或 WebP),MapLibre 直接显示:

  • 无法客户端重设样式或查询要素
  • 文件体积较大,但生成和提供服务更简单
  • 适用于卫星/航拍影像、WMS/WMTS 集成,或无需客户端定制的渲染风格

多数 MapLibre 工作流使用矢量瓦片;越来越多场景集成 raster-dem 数据源(例如地形渲染)。当需要卫星/航拍影像、与现有 WMS 或 WMTS 服务集成,或需要预渲染制图风格时,可使用栅格瓦片。

在 Leaflet 中使用 MapLibre

Leaflet 是广泛使用的 JavaScript 地图库,仅支持栅格瓦片。如果你的应用基于 Leaflet 构建,MapLibre GL Leaflet 允许将兼容 MapLibre GL 的样式预渲染为栅格图层——从而在 Leaflet 应用中使用托管矢量瓦片数据源。

组合多种数据源类型

一个 MapLibre 样式可同时包含任意数量的各类数据源。来自不同数据源的图层按绘制顺序合成。因此自然地可根据不同目的混合使用数据源。

数据源可在自定义样式表中组合,也可在运行时动态添加。注意图层顺序很重要:图层在样式中按出现的顺序从下往上绘制。若栅格图层添加到矢量图层之后,将会遮挡它们。

  • 矢量底图 + GeoJSON 叠加层 — 最常见的模式。使用服务商的样式 URL(或任何矢量瓦片数据源)作为底图,并通过 map.addSource()map.addLayer() 在上层添加自己的数据。为保持标注可读,应将你的图层插入到第一个符号图层之前,而非追加到顶层。
// 从任意底图样式 URL 开始,然后将自己的数据添加到标注下方
map.on('load', () => {
  // 找到第一个符号(标注)图层的 ID,以便插入到其下方
  const firstSymbolId = map.getStyle().layers.find((l) => l.type === 'symbol')?.id;

  map.addSource('my-data', { type: 'geojson', data: '/path/to/data.geojson' });
  map.addLayer(
    { id: 'my-layer', type: 'circle', source: 'my-data' },
    firstSymbolId // 插入到标注之前;省略则追加到所有图层上方
  );
});
  • 栅格影像 + 矢量标注 — 添加栅格数据源用于卫星影像、气象雷达、历史影像、服务端渲染的热力图等无法作为矢量数据获得的影像。再添加矢量数据源用于道路、地名等标注。这样既获得清晰影像,又保留了分辨率无关的清晰矢量几何和标注。
  • 矢量底图 + raster-dem 地形 — 使用 raster-dem 数据源(高程瓦片)为任何矢量底图添加山体阴影或 3D 地形。这就是 MapLibre 无需单独底图样式即可渲染地形和山体阴影的方式。

各场景方案选择

大多数实际应用会组合使用数据源类型——用托管底图作为参考层,用自己的数据作为独立数据源。你很少需要仅为自己的数据构建一套定制瓦片管线。

场景 推荐数据源配置
< 约 5,000 个要素,需要点击/悬停交互或实时更新 GeoJSON — 无需瓦片服务器
5,000–100,000 个要素 若可接受简化几何和 1–3 秒加载延迟则用 GeoJSON;否则使用矢量瓦片
> 100,000 个要素或 > 50 MB 矢量瓦片 — 用 tippecanoe 或 Planetiler 生成
街道、地形或地名底图 托管瓦片服务(OpenFreeMap、MapTiler)或自托管(Martin)
在任意底图上叠加自己的数据 托管底图样式 URL + 自己的数据作为独立 GeoJSON 或矢量瓦片数据源
卫星/航拍影像 + 标注 栅格瓦片数据源(影像)+ 矢量数据源(道路和标注)

关键区别在于:底图和你自己的数据几乎总是分开的数据源,即便两者都是矢量瓦片。底图提供上下文;你的数据源提供应用数据。除非你需要完全掌控瓦片管线自建托管地图,否则很少需要将它们合并为单一自定义瓦片源。

托管瓦片数据源

“托管”瓦片数据可指两种不同方式:

  • 在 Web 上存储文件 — 一个 .pmtiles 归档文件(或预生成的瓦片目录)放在静态存储如 S3、R2 或 GitHub Pages 上。无服务器进程运行;MapLibre 通过 HTTP 范围请求或标准 HTTP 获取瓦片。更新需要重新生成并重新上传文件。
  • 运行瓦片服务器 — 一个服务器进程动态处理瓦片请求,通常从数据库(PostGIS)或源文件(MBTiles、PMTiles)中读取。支持实时数据和即时生成,但需要部署和持续维护。

下面三种方案对应上述两种途径:PMTiles 基于文件且无需服务器;托管瓦片服务商替你运行瓦片服务器基础设施;自托管意味着你自行运行服务器。

无服务器(PMTiles)

PMTiles 是一种开放的单一文件瓦片格式,支持矢量或栅格瓦片——MapLibre 通过 HTTP 范围请求仅获取所需的字节范围,无需瓦片服务器。只需提取所需地理范围,将 .pmtiles 文件托管在静态存储(S3、R2、GitHub Pages)即可。

参见 maplibre-pmtiles-patterns 了解配置方法。

托管瓦片服务

许多服务商提供托管矢量或栅格瓦片,以及预建样式和瓦片 URL——无需自行运行服务器。完整列表见 awesome-maplibre 的地图/瓦片提供商

若想无需 API 密钥即可开始,OpenFreeMap 提供免费的托管 OpenStreetMap 瓦片及适配 MapLibre 的样式(https://tiles.openfreemap.org/styles/liberty/positron)。该项目由社区资助——如果你的应用在生产环境中依赖它,请考虑捐赠或自托管以减轻共享基础设施负载。

请勿在生产环境或非常有限的测试之外使用 tile.openstreetmap.org。OpenStreetMap 基金会禁止大量及高流量使用其瓦片服务器;违规将导致 IP 被封。请改用托管服务商或自托管。当前服务商列表见 switch2osm.org/providers

  • ✅ 全球 CDN;有预建样式可用
  • ✅ 覆盖全球到本地尺度
  • ⚠️ 自定义样式图层定义必须匹配托管瓦片源的 schema
  • ⚠️ 供应商依赖
  • ⚠️ 多数需要 API 密钥;检查许可、使用限制和定价
  • ⚠️ 基于 OpenStreetMap 的瓦片必须提供署名——视觉突出程度与其他署名相当。OpenStreetMap 数据基于 ODbL 许可;若你从 OSM 数据创建衍生数据库,相同方式共享条款要求你同样以 ODbL 发布。社区资助的免费服务有使用政策;请遵守,并在使用量增长时通过自托管或捐赠回馈社区

将 API 密钥存储在环境变量中;切勿提交到源代码控制。

自托管瓦片服务器

运行自己的服务器以完全控制数据、成本和部署。可选方案见 awesome-maplibre 的瓦片服务器,包括 MapLibre 维护的 💙 Martin。可使用现有瓦片 schema,或通过 Planetilertippecanoe 生成自定义瓦片。

  • ✅ 完全控制;大规模时无单次请求成本
  • ✅ 可服务动态数据并即时转换为瓦片
  • ✅ 支持离线/隔离部署
  • ⚠️ 需要处理数据,并部署维护基础设施。全球 OpenStreetMap 数据集约需 1 TB 存储和 24 GB 内存;城市级提取约需 10–20 GB 存储和 4 GB 内存。当前硬件建议见 switch2osm.org
  • ⚠️ 必须配置 CORS 并在样式中提供字形和精灵图

自定义样式

自定义样式是你自己编写的样式,而非使用服务商提供的预建样式 URL。自定义样式可引用托管或自托管瓦片数据源——实际上最常见的是两者结合的模式:

  • 托管瓦片数据源 — 你的样式 JSON 指向服务商的瓦片 URL。你控制视觉外观,依赖服务商提供瓦片传输。图层定义必须匹配服务商的瓦片 schema,且通常复用其字形和精灵图。
  • 自托管瓦片数据源 — 你的样式 JSON 指向自己的瓦片服务器或 PMTiles 文件。你同时控制样式和数据,但必须自行提供字形和精灵图(或复用与瓦片 schema 匹配的公开资源)。

实际中最常见的模式是混合式:一个自定义样式引用托管服务商的底图瓦片——并常复用其字形和精灵图——同时为自己的数据添加自托管瓦片源或 GeoJSON 叠加层。这样无需从头构建底图瓦片基础设施,即可完全控制自己的数据图层。

预定义瓦片 Schema

构建自定义样式时(而非使用服务商预建样式 URL),你需要了解瓦片 schema——即 source-layer 的名称及其属性。样式的图层定义必须与瓦片数据源的 schema 匹配。

常见 schema:

  • OpenMapTiles — 应用最广泛的 schema,基于 OpenStreetMap 数据。丰富且详细,包含 transportationwaterlandusepoi 等 source-layer。最大的社区样式生态均针对此 schema。
  • Shortbread — 开放标准,设计上追求最小化和互操作性,不绑定单一供应商。结构比 OpenMapTiles 更简单;是从头构建样式的干净基础。
  • Protomaps — 专为 Protomaps PMTiles 底图生态构建。扁平简单结构,包含 landwaterroadsplaces 等 source-layer;为无服务器传输优化。

若使用服务商的预建样式 URL,schema 已自动匹配。

字形(字体)与精灵图

每个显示文字或图标的 MapLibre 样式都需要:

  • glyphs: 字体堆栈的 URL 模板 — "glyphs": "https://example.com/fonts/{fontstack}/{range}.pbf"
  • sprite: 精灵表单和元数据的基 URL(同时提供 .json.png) — "sprite": "https://example.com/sprites/basic"

托管服务商的预建样式 URL 已包含其自身的字形和精灵图。构建自定义样式或自托管时,你必须提供这些 URL。

若你基于某个预定义瓦片 schema 修改样式,可寻找匹配该 schema 的现有样式,并复用其字形和精灵图。复用资源时请注意许可和署名要求。如有需要,你也可以下载这些文件并从自己的存储或瓦片服务器提供服务。

另一种选择是自己生成字形和精灵表单。生成工具见 awesome-maplibre 的字体字形生成精灵图生成 章节。

TileJSON

TileJSON 是描述瓦片集的 JSON 标准格式——包含瓦片 URL 模板、缩放范围、边界、中心点、署名,以及(对于矢量瓦片)可用的 source-layer。瓦片服务器和服务商提供 TileJSON 端点;MapLibre 可直接消费。

在数据源中引用瓦片

瓦片通过缩放级别 (Z)、列号 (X) 和行号 (Y) 寻址——这是栅格和矢量瓦片源通用的方案(更多信息见 OpenStreetMap wiki)。在 MapLibre 数据源中,你可以通过 tiles URL 模板直接引用瓦片,或通过指向 TileJSON 端点的 url 引用。

若存在 TileJSON 端点,优先使用 url:MapLibre 获取该文档后自动读取瓦片 URL 模板、缩放范围、边界、署名,以及(对于矢量瓦片)可用的 source-layer。像 Martin 和 tileserver-gl 这样的瓦片服务器会为每个服务的瓦片集自动生成 TileJSON 端点,许多托管服务商也是如此。

若无 TileJSON 端点——例如直接提供一个原始栅格瓦片服务的 URL 模板——则使用 tiles 数组并在数据源定义中自行指定元数据(minzoom、maxzoom、attribution)。

tiles 数组:

{
  "type": "vector",
  "tiles": ["https://example.com/tiles/{z}/{x}/{y}.pbf"],
  "minzoom": 0,
  "maxzoom": 14
}

url 指向 TileJSON 端点:

{
  "type": "vector",
  "url": "https://example.com/tiles.json"
}

TileJSON 与自定义样式

对于矢量数据源,TileJSON 的 vector_layers 字段列出了每个可用的 source-layer、其属性字段及缩放范围。构建自定义样式时,这是权威参考:图层定义中引用的 source-layer 名称必须与此处完全一致。

使用 Planetiler 或 tippecanoe 生成瓦片时,输出文件会将 TileJSON 元数据嵌入 MBTiles 或 PMTiles 文件。像 Martin 这样的瓦片服务器会自动读取这些元数据并以 TileJSON 端点形式暴露。

CORS

若你的瓦片、字形或精灵图位于不同源,服务器必须发送 CORS 头(Access-Control-Allow-Origin)。否则浏览器会阻止请求,地图将显示空白或缺失标注。

托管服务商会为你处理 CORS。对于自托管服务器或静态存储,需在服务器或 CDN 上配置 CORS。

相关技能

  • maplibre-pmtiles-patterns — 无服务器 PMTiles 托管及 MapLibre 集成。
  • maplibre-style-patterns — 常见场景的图层与数据源配置。(暂未加入仓库。)
  • maplibre-mapbox-migration — 将 Mapbox 瓦片替换为 MapLibre 兼容数据源。

参考资料

  1. GeoJSON 性能阈值(文件大小 / 要素数量范围)— 汇总自 Stack Overflow、Reddit、Medium 和 Cesium Community Forum 的社区经验法则。⚠️ 非官方或规范性来源
  2. PMTiles 格式与 HTTP 范围请求协议docs.protomaps.com/pmtiles/
  3. Protomaps(预建 PMTiles 底图) — protomaps.com
  4. Planetiler(从 OSM 生成矢量瓦片) — GitHub
  5. tippecanoe(从 GeoJSON 生成矢量瓦片) — github.com/felt/tippecanoe
  6. Martin 瓦片服务器maplibre.org/martin/
  7. MapLibre Tile (MLT) 规范maplibre.org/maplibre-tile-spec/
  8. OpenMapTiles schemaOpenMapTiles.org
  9. Shortbread 瓦片 schemashortbread-tiles.org
  10. Leafletleaflet.js
  11. MapLibre GL Leafletgithub.com/maplibre/maplibre-gl-leaflet
  12. 云原生地理空间格式:FlatGeobuf (flatgeobuf.org)、GeoParquet (GeoParquet)、Cloud-Optimized GeoTIFF (COG 网站)
  13. awesome-maplibregithub.com/maplibre/awesome-maplibre
  14. switch2osm.org — 从 Google Maps 切换至基于 OSM 瓦片托管的社区指南,包含服务商列表、自托管技术栈、硬件要求和 ODbL 许可指导 — switch2osm.org

3 maplibre-pmtiles-patterns.md


名称: maplibre-pmtiles-patterns
描述: 面向 MapLibre GL JS 的 PMTiles 无服务器矢量与栅格瓦片方案 — 单文件格式、HTTP 范围请求、托管于 S3/R2/GitHub Pages、使用 Planetiler 或 tippecanoe 生成、以及 pmtiles 协议。适用于无需瓦片服务器或希望从静态存储托管瓦片的场景。


MapLibre PMTiles 使用模式

PMTiles 是一种用于矢量或栅格地图瓦片的单一文件格式。你将一个(或几个)文件托管在任意静态主机上;MapLibre 通过 HTTP 请求字节范围。无需瓦片服务器,无需动态后端。本技能涵盖何时使用 PMTiles、如何生成和托管它们,以及如何将它们接入 MapLibre GL JS。

何时使用此技能

  • 在不运行瓦片服务器的情况下托管地图瓦片(S3、Cloudflare R2、GitHub Pages 等)
  • 构建完全静态或无服务器的地图技术栈
  • 通过支持范围请求的 CDN 提供大型瓦片集
  • 从 OSM 或其他数据源生成 PMTiles(Planetiler、tippecanoe)
  • 在 MapLibre 中使用 Overture Maps 或其他单文件瓦片数据集

什么是 PMTiles 及其价值

  • 矢量与栅格 — PMTiles 两者均支持。一个文件可包含矢量图层(如水域、道路、POI)、栅格影像(PNG/JPEG)或栅格高程(raster-dem,例如用于地形的 Terrarium 格式)。在样式中相应使用 type: 'vector'type: 'raster'type: 'raster-dem'
  • 每张地图一个文件 — 一个 .pmtiles 文件通常包含完整的瓦片金字塔(所有缩放级别)和所有图层(矢量或栅格),打包于一个归档中。该格式以紧凑布局(如希尔伯特曲线)存储瓦片,客户端仅需请求所需的字节范围。对于非常大范围的覆盖,可按区域拆分为多个文件。
  • HTTP 范围请求 — 客户端仅请求其需要的字节范围(例如单个瓦片),因此服务器无需理解 x/y/z 概念。任何支持 Range 头的主机均可工作。
  • 提供服务 — 你可以直接从静态存储(S3、R2、GitHub Pages、Netlify)提供服务:客户端使用范围请求,因此无需瓦片服务器。或者,tileserver-glMartin 也可提供 PMTiles(从本地路径、HTTP URL 或 S3),若你希望有一个同时提供样式、字形或其他数据源的服务器,这很有用。
  • 创建 PMTiles — 你可以通过从 MBTiles 转换(使用 PMTiles CLI),或从源数据生成(Planetiler、tippecanoe、GDAL 等)来获取 PMTiles。此外,Protomaps 是一个可下载预构建 PMTiles(例如全球或区域底图)并自行提供服务的提供商,也可通过 PMTiles CLI 创建自定义提取——无需自行从 OSM 生成。Protomaps 底图基于 OpenStreetMap 数据构建;任何使用它们的地图都必须提供 OSM 署名。参见下方的 PMTiles CLI生成 PMTiles
  • 适合 CDN — 范围请求具有良好的缓存特性;将文件置于 CDN 后,可实现快速的全球访问。

何时优先选择 PMTiles 而非传统瓦片服务器:

  • 你希望零服务器逻辑(仅静态托管)。
  • 你有一个有界的数据集(国家、区域、主题),适合放入一个或几个文件。
  • 你希望部署简单、运维成本低(上传文件、设置缓存头,即可完成)。

何时优先选择瓦片服务器(如 tileserver-gl、Martin):

  • 你需要从数据库(PostGIS)生成动态瓦片,或数据频繁更新。
  • 你拥有非常大的全球数据集,并希望按需或仅按区域生成瓦片。

MapLibre 集成:PMTiles 协议

MapLibre 本身不能直接处理 PMTiles。你需要使用 PMTiles 库添加一个协议处理器,使 pmtiles://(或指向 .pmtiles 文件的 https://)数据源能够正常工作。

安装:

npm install pmtiles

注册协议并在样式中使用:

import * as pmtiles from 'pmtiles';
import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';

// 添加 PMTiles 协议,使数据源可引用 .pmtiles URL
const protocol = new pmtiles.Protocol();
maplibregl.addProtocol('pmtiles', protocol.tile);

const map = new maplibregl.Map({
  container: 'map',
  style: {
    version: 8,
    sources: {
      tiles: {
        type: 'vector',
        url: 'pmtiles://https://example.com/data.pmtiles'
      }
    },
    layers: [
      {
        id: 'background',
        type: 'background',
        paint: { 'background-color': '#f8f4f0' }
      },
      {
        id: 'water',
        type: 'fill',
        source: 'tiles',
        'source-layer': 'water',
        paint: { 'fill-color': '#a0c8f0' }
      }
      // 根据需要添加更多图层——每个图层使用相同的数据源,但指定不同的 'source-layer'
    ]
  },
  center: [0, 0],
  zoom: 2
});

// 可选:在地图销毁时移除协议
// map.on('remove', () => maplibregl.removeProtocol('pmtiles'));

引用图层: 样式中有一个数据源(如 sources.tiles)指向 .pmtiles URL。layers 数组中每个从该文件绘制的图层使用 source: 'tiles'"source-layer": "图层名称",其中 图层名称 是文件内部矢量图层的名称(遵循瓦片所使用的任意 schema)。通过添加多个具有不同 source-layer 值的样式图层,可以从同一文件中显示道路、标注等。

重要提示: url 可以是 pmtiles://https://...(协议 + HTTPS URL 指向 .pmtiles 文件)。该库将通过范围请求获取文件。如果你使用标注或图标,样式仍必须定义字形和精灵图(参见 maplibre-tile-sources)。

栅格与栅格高程: 相同的协议适用于栅格 PMTiles。对于影像,使用 type: 'raster' 数据源。对于地形/高程,使用 type: 'raster-dem' 数据源,并设置 "encoding": "terrarium"(或 "mapbox"),以便 MapLibre 应用山体阴影或 3D 地形;然后在样式的 terrain 属性中引用它。数据源示例:

"elevation": {
  "type": "raster-dem",
  "url": "pmtiles://https://example.com/elevation.pmtiles",
  "encoding": "terrarium"
}

在 React 中使用 PMTiles: 在应用启动时注册一次协议,而非在每个组件内注册,以确保在任何地图挂载前 MapLibre 已有该处理器。例如,在根级 effect 或地图提供者初始化时调用 maplibregl.addProtocol('pmtiles', protocol.tile)。在最后一个地图卸载(或应用销毁)时,调用 maplibregl.removeProtocol('pmtiles') 以避免泄漏。关于 React 相关配置,参见 PMTiles for MapLibre GL(Protomaps 文档)。

托管 PMTiles

任何能够提供文件并支持 HTTP 范围请求 的主机都适用。

  • AWS S3 — 启用公共读取(或签名 URL);S3 支持 Range。设置 Cache-Control,并可选用 CloudFront。
  • Cloudflare R2 — 兼容 S3;启用公共访问或使用签名 URL。置于 Cloudflare 后以获得缓存加速。
  • GitHub Pages — MapLibre GL JS 可以从同一仓库中的 .pmtiles 文件加载瓦片,只要文件大小不超过 100 MB。
  • Netlify / Vercel — 上传 .pmtiles 文件;静态托管通常支持 Range。请检查各服务商的文件大小限制。
  • 任意静态主机 — 确保服务器返回 Accept-Ranges: bytes 并正确响应 Range 头。

CORS: 浏览器将向 PMTiles URL 发送跨域请求。主机必须发送 Access-Control-Allow-Origin: *(或你的域名)以及 Access-Control-Allow-Headers: Range(或允许所有头)。否则 MapLibre 将无法加载瓦片。

缓存头: 为获得更好性能,为 .pmtiles 文件设置长期缓存(例如,如果文件不可变,设置 Cache-Control: public, max-age=31536000)。CDN 将缓存范围请求的响应。

PMTiles CLI

pmtiles CLI 是用于处理 PMTiles(以及转换用 MBTiles)的官方命令行工具。它是一个单一二进制文件,无运行时依赖——下载即可运行。

为何安装并使用它:

  • 将 MBTiles 转换为 PMTiles — 许多工具(tippecanoe、GDAL、martin-cp)输出 MBTiles。只需一条命令即可将任何 .mbtiles 文件转换为 .pmtiles 文件:pmtiles convert in.mbtiles out.pmtiles。当你的处理流程已产出 MBTiles 时,这通常是获取 PMTiles 的最简单方式。
  • 检查与验证归档文件pmtiles show <文件> 打印头部和元数据(边界、缩放范围、瓦片数量)。pmtiles verify <文件> 检查归档完整性。在上传前调试或确认文件时很有用。
  • 提取子集pmtiles extract 可从现有文件创建较小的 .pmtiles 文件(例如按边界框或缩放范围),从而无需从源数据重新生成即可分发特定区域或有限缩放范围的瓦片。

安装:GitHub Releases (go-pmtiles) 下载适用于你操作系统/架构的二进制文件,或使用 Docker:protomaps/go-pmtiles

它不做什么: CLI 仅处理瓦片归档(MBTiles 和 PMTiles)。它不读取 GeoJSON、Shapefile、OSM 或其他源格式。要从这些格式创建 PMTiles,请使用能够生成瓦片的工具(参见下方 生成 PMTiles),如果该工具输出 MBTiles,再运行 pmtiles convert 以获得 PMTiles。

生成 PMTiles

两种途径: (1) 转换 — PMTiles CLI 仅执行 MBTiles ↔ PMTiles 转换;它不读取 GeoJSON、Shapefile、OSM 或其他源格式。(2) 从源数据生成 — 诸如 tippecanoe、Planetiler 以及通过 GDAL 的 ogr2ogr 等工具可从多种文件类型或数据库读取并生成矢量瓦片(PMTiles 或 MBTiles)。如果它们输出 MBTiles,则使用 pmtiles convert 获取 PMTiles。

PMTiles CLI(仅转换:MBTiles ↔ PMTiles)

关于为何安装它以及其他命令(showverifyextract),请参阅上文的 PMTiles CLI。将 MBTiles 转换为 PMTiles:

pmtiles convert input.mbtiles output.pmtiles

以下工具从源数据生成瓦片(GeoJSON、OSM、Shapefile、PostGIS 等)。它们输出 PMTiles 或 MBTiles;如果输出 MBTiles,则运行 pmtiles convert 获取 PMTiles。

Planetiler(OSM / OpenMapTiles schema)

Planetiler 读取 OpenStreetMap(或其他数据源)并输出遵循 OpenMapTiles schema 的 PMTiles 或 MBTiles。

# 示例:为某个区域构建 PMTiles 文件(例如,从下载的 .osm.pbf 文件)
java -jar planetiler.jar --area=monaco --output=monaco.pmtiles

有关区域名称、自定义数据源和 schema 选项,请参阅 Planetiler 文档。输出是一个单一的 .pmtiles 文件,可上传到 S3/R2/静态主机。

tippecanoe

tippecanoe 从源格式生成矢量瓦片:GeoJSON、FlatGeobuf、CSV。自 v2.17 起,它可以直接输出 PMTiles-o output.pmtiles)。你也可以输出 MBTiles 再用 pmtiles convert 转换。

# 直接输出 PMTiles(v2.17+)
tippecanoe -zg -o output.pmtiles input.geojson
# 或输出 MBTiles 然后转换:tippecanoe -o output.mbtiles -z 14 input.geojson && pmtiles convert output.mbtiles output.pmtiles

ogr2ogr(GDAL)

GDAL 的 ogr2ogr 可从多种地理空间格式(Shapefile、PostGIS、GeoJSON 等)生成瓦片,并可写入 MBTiles 或 PMTiles(GDAL 3.8+)。对于小型数据集最适用;对于大型矢量瓦片集,tippecanoe 效率更高。

栅格与栅格高程 PMTiles

PMTiles 支持栅格瓦片(PNG/JPEG,例如卫星或预渲染影像)和栅格高程(高程/地形,例如 Terrarium 或 Mapbox 编码)。使用能够生成栅格或栅格高程 PMTiles 的工具;相同的协议和托管方式适用。在样式中,对于影像使用 type: 'raster',对于地形使用 type: 'raster-dem' 并设置 "encoding": "terrarium"(或 "mapbox")——示例参见上方 MapLibre 集成 部分。

Overture Maps

Overture Maps 发布全球开放地图数据。一些服务商以 PMTiles 形式分发基于 Overture 的数据(例如建筑物、场所、交通)。你也可以使用 Planetiler 或其他流程从 Overture 数据构建 PMTiles。像上面一样在 MapLibre 样式中使用 PMTiles URL 即可。

性能建议

  • CDN — 通过 CDN(CloudFront、Cloudflare)提供 .pmtiles 文件,使范围请求在全球范围内快速响应。
  • 压缩 — PMTiles 存储已压缩的瓦片;该库负责解压缩。确保服务器不会以破坏范围请求的方式对整个文件进行二次压缩(例如 gzip)。
  • 多个文件 — 对于非常大的覆盖范围,可按区域拆分为多个 .pmtiles 文件,并根据边界切换数据源 URL 或使用多个数据源。
  • 缓存 — 为文件设置强缓存头;浏览器和 CDN 将缓存范围请求的响应。

相关技能

  • maplibre-tile-sources — 选择瓦片数据源(OpenFreeMap、MapTiler、PMTiles、自托管);字形与精灵图。
  • maplibre-style-patterns — 矢量数据源(包括基于 PMTiles 的数据源)的图层与绘制配置。(暂未加入仓库。)

参考资料

4 maplibre-mapbox-migration.md


名称: maplibre-mapbox-migration
描述: 从 Mapbox GL JS 迁移至 MapLibre GL JS — 包与导入变更、移除访问令牌、选择瓦片数据源、插件等效方案,以及收益与取舍。适用于将现有 Mapbox 地图迁移至 MapLibre 的场景。


Mapbox 迁移至 MapLibre

本技能将引导你将应用从 Mapbox GL JS 迁移至 MapLibre GL JS。这两个库同出一源(MapLibre 于 2020 年 12 月从 Mapbox GL JS v1.13 分叉而来),因此 API 基本相同。主要变更包括:替换 npm 包、替换命名空间、移除 Mapbox 访问令牌,以及选择新的瓦片数据源(MapLibre 不使用 mapbox:// 样式)。

主要参考: MapLibre 官方 Mapbox 迁移指南

何时使用此技能

  • 将现有 Mapbox GL JS 应用迁移至 MapLibre
  • 评估 MapLibre 作为 Mapbox 的开源替代方案
  • 了解 API 兼容性及破坏性变更
  • 离开 Mapbox 后选择瓦片数据源与服务

为何迁移至 MapLibre?

团队从 Mapbox 转向 MapLibre 的常见原因:

  • 开源许可证 — MapLibre 采用 BSD-3-Clause 许可;无供应商锁定或专有条款
  • 无需访问令牌 — 库本身不要求 Mapbox 令牌;瓦片数据源可能有自己的密钥或完全无需密钥(例如 OpenFreeMap)
  • 成本 — 避免 Mapbox 地图加载及 API 计费;使用免费或固定成本的瓦片和地理编码提供商
  • 自托管 — 使用自己的瓦片(PMTiles、tileserver-gl、Martin)或任意第三方数据源
  • 社区 — MapLibre 由 MapLibre 组织及社区维护;样式规范与 API 在公开环境中演进
  • 社区资助模式 — MapLibre 由众多公司和个人捐赠资助;没有单一商业支持方,因此项目始终与社区利益保持一致
  • 开放的矢量瓦片格式(MLT) — MapLibre 提供 MapLibre Tile(MLT),作为 Mapbox Vector Tiles(MVT)的现代替代方案,具有更好的压缩率,支持三维坐标和高程;在 GL JS 和 Native 中均受支持,并可通过 Planetiler 生成

你将放弃什么: Mapbox Studio 集成、Mapbox 托管的瓦片与样式、Mapbox Search/Directions/Geocoding API、Mapbox 官方技术支持。

理解分叉背景

  • 2020 年 12 月: Mapbox GL JS v2.0 转为专有许可证。社区从 v1.13 分叉出 MapLibre GL JSMapLibre 组织GL JS 仓库 是官方项目地址。
  • API: MapLibre GL JS v1.x 与 Mapbox GL JS v1.x 大体向后兼容。多数地图代码(方法、事件、图层、数据源)只需少量改动即可工作。
  • 分叉后的版本发布: MapLibre 已沿自身版本线前进。v2/v3 引入了 WebGL2、现代渲染器以及山体阴影和地形等特性;v4 在公共 API 中引入 Promise(取代大量回调);v5 增加了地球视图和自适应复合地图投影。参见 releasesCHANGELOG
  • 样式规范: MapLibre 维护自己的 MapLibre 样式规范(从 Mapbox 规范分叉)。多数样式兼容,但在某些方面已有新增和分化;使用较新或 MapLibre 专有特性时,请查阅样式规范网站
  • 生态系统: 除 GL JS 外,MapLibre 组织还托管 MapLibre Native(iOS、Android、桌面端)、Martin(从 PostGIS/PMTiles/MBTiles 提供矢量瓦片的瓦片服务器)以及 MapLibre Tile(MLT) 格式。路线图与新闻:maplibre.org/roadmapmaplibre.org/news

分步迁移指南

1. 安装软件包

npm install maplibre-gl

2. 更新导入与 CSS

// 迁移前(Mapbox)
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';

// 迁移后(MapLibre)
import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';

CDN: 将 Mapbox 的 script/link 替换为 MapLibre:

  • Script: https://api.mapbox.com/mapbox-gl-js/v*.*.*/mapbox-gl.jshttps://unpkg.com/maplibre-gl@*.*.*/dist/maplibre-gl.js
  • CSS: 同理(mapbox-gl.css → maplibre-gl.css)。

3. 替换命名空间

将所有 mapboxgl 替换为 maplibregl(包名或路径中的 mapbox-gl 也替换为 maplibre-gl)。示例:

// 迁移前(Mapbox)
const map = new mapboxgl.Map({ ... });
new mapboxgl.Marker().setLngLat([lng, lat]).addTo(map);
map.addControl(new mapboxgl.NavigationControl());

// 迁移后(MapLibre)
const map = new maplibregl.Map({ ... });
new maplibregl.Marker().setLngLat([lng, lat]).addTo(map);
map.addControl(new maplibregl.NavigationControl());

CSS 类名: 如果你通过类名自定义控件或 UI 样式,请将 mapboxgl-ctrl 重命名为 maplibregl-ctrl(以及类似前缀)。

4. 移除访问令牌

MapLibre 不使用 mapboxgl.accessToken。移除所有设置该属性的代码行。

瓦片和 API 密钥(例如用于托管瓦片服务或地理编码)需按服务单独配置,而非在 map 实例上设置。需要密钥的服务商列表参见 maplibre-tile-sources

5. 替换样式 URL(关键步骤)

Mapbox 样式(mapbox://styles/...)无法在 MapLibre 中使用。你必须将地图指向一个使用非 Mapbox 瓦片数据源、精灵图和字形的样式。

最简单的选项是使用无需 API 密钥的样式 URL,例如 OpenFreeMap。OpenFreeMap 由社区资助,免费使用且无需 API 密钥;若你的应用在生产环境中依赖它,请考虑捐赠以支持该项目。验证迁移工作正常后,可进一步探索众多可用选项(更多建议参见 awesome-maplibreMapLibre Tile Sources)。

示例:

// 迁移前(Mapbox)
const map = new mapboxgl.Map({
  container: 'map',
  style: 'mapbox://styles/mapbox/streets-v12',
  center: [-122.42, 37.78],
  zoom: 12
});

// 迁移后(MapLibre)
const map = new maplibregl.Map({
  container: 'map',
  style: 'https://tiles.openfreemap.org/styles/liberty', // 或你选择的其他样式
  center: [-122.42, 37.78],
  zoom: 12
});

此后,你可以安装 MapLibre Style Specification & Utilities 来验证和调试样式:

npm install @maplibre/maplibre-style-spec

自定义 Mapbox 样式: 如果你在 Mapbox Studio 中设计了样式,无法直接在 MapLibre 中加载。需要导出样式 JSON,并将 Mapbox 数据源 URL 替换为你所选瓦片数据源的 URL。除非且直至你将所有引用 Mapbox 瓦片 schema 的地方调整为新瓦片数据源的 schema,否则样式将无法渲染。 除了更新数据源 URL,这还意味着需要修改样式 JSON 中的 idsourcesource-layer 属性,以匹配新数据源和图层名称。

Mapbox 样式中的多数属性与 MapLibre 兼容。关于支持的属性和类型细节,请查阅 MapLibre 样式规范。你可以使用 MapLibre 的样式编辑器 Maputnik 可视化测试和调试样式 JSON,并使用 MapLibre Style Spec CLI Tools 检查兼容性和其他验证问题。

gl-style-validate style.json

6. 更新插件(若使用)

许多 Mapbox 插件无需修改即可在 MapLibre 中工作,也有许多已被分叉或替换为 MapLibre 原生版本。为长期兼容考虑,若存在 MapLibre 原生替代方案,应优先选用。

awesome-maplibre 的用户界面插件、地理编码与搜索插件以及地图渲染插件章节中,可找到兼容插件及替代方案。

7. 替换 Mapbox API(搜索、路线等)

若你的应用调用了 Mapbox Geocoding、Directions 或其他 REST API,请替换为开放或第三方服务:

使用政策与可持续性: 这些是开放或社区资助的服务,生产环境中需注意其条款:

  • Nominatim — 要求 OpenStreetMap 署名;公共实例仅供测试和低流量使用。参见 Nominatim 使用政策。生产级工作负载请自托管或使用托管服务(例如 MapTiler Geocoding)。
  • OSRM 演示服务器router.project-osrm.org)— 明确不用于生产环境;无 SLA 或正常运行时间保证。生产应用请自托管或使用托管服务(例如 OpenRouteService、MapTiler Directions)。
  • 若你的应用大规模依赖社区维护的服务,请回馈社区:自托管以减轻共享基础设施负担、捐赠,或向上游贡献代码或文档。

更新代码以使用新的端点及响应格式;地图图层和交互代码(例如添加路线折线)在 MapLibre 中保持不变。

8. 保持不变的部分

你的大部分地图代码无需修改:

  • 地图方法:setCentersetZoomfitBoundsflyTogetBounds
  • 事件:map.on('load')map.on('click', layerId, callback)
  • 标记、弹出框、控件(导航、定位、全屏、比例尺)
  • 数据源与图层:addSourceaddLayersetPaintPropertysetFilter
  • 样式规范中的 GeoJSON 与表达式

因此,在替换包、命名空间、令牌和样式(以及任何插件/API)之后,其余逻辑均可保持原样。

检查清单

  • 卸载 mapbox-gl,安装 maplibre-gl
  • 替换导入与 CSS(mapbox-gl → maplibre-gl)
  • 将所有 mapboxgl 替换为 maplibregl(CSS 类名 mapboxgl-maplibregl-
  • 移除 mapboxgl.accessToken
  • style 设置为非 Mapbox URL(托管样式或你自己的样式)
  • 将不兼容的 Mapbox 插件替换为 MapLibre 或开源替代方案
  • 将 Mapbox Geocoding/Directions 替换为 Nominatim、OSRM 或其他开源替代服务
  • 测试地图加载、控件及所有依赖 API 的功能

相关技能

本技能参考来源

创建本技能时使用了以下来源。你可能希望邀请维护或贡献过这些来源的贡献者参与:

  1. MapLibre 官方迁移指南maplibre.org/maplibre-gl-js/docs/guides/mapbox-migration-guide/ — 主要分步参考(包、命名空间、CSS、CDN)。
  2. MapLibre GL JS 文档maplibre.org/maplibre-gl-js/docs/ — API 与概念。
  3. MapLibre GL JS GitHubgithub.com/maplibre/maplibre-gl-js — README、发布说明与分叉历史。
  4. mapbox-agent-skills — 其中的 mapbox-maplibre-migration 技能(Mapbox 仓库)涵盖反向迁移(MapLibre → Mapbox)。本技能(Mapbox → MapLibre)借鉴了其主题结构和对比元素。改编部分版权归 Mapbox, Inc. 所有。
  5. 本仓库的技能maplibre-tile-sourcesmaplibre-pmtiles-patterns;尚未收入仓库的 maplibre-open-search-patterns 与 maplibre-geospatial-operations — 关于迁移后的瓦片数据源与服务替代方案。
Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐