麻辣GIS微信平台

更多 GIS 干货

微信关注不错过

geojson-vt:540万点GeoJSON浏览器秒开,开源矢量切片神器

最近小编在做 WebGIS 项目时,经常遇到大 GeoJSON 文件加载卡死的问题,之前大家的默认做法是要么用 tippecanoe 之类的工具预先切成矢量瓦片,要么起后端服务动态处理,一个占存储一个占服务器,都不省心。小编最后发现 Mapbox 开源了一个叫 geojson-vt 的库,纯前端就能把 GeoJSON 按需切片成矢量瓦片,官方 Demo 里 100 MB、540 万个点的美国邮编数据也能在浏览器里顺畅渲染,今天小编就带大家看看这个库。

geojson-vt 简介

geojson-vt 是 Mapbox 开源的高效 JavaScript 库,核心功能是把 GeoJSON 数据在浏览器端动态切片成矢量瓦片,在“无服务器”场景下完成大型空间数据渲染与交互。这个库 2015 年就开源了,作者是 Vladimir Agafonkin,也就是 Leaflet 的作者。它最初就是为了支撑 Mapbox GL JS 的 GeoJSON 数据源而写的,后来 Leaflet、OpenLayers、d3 以及 Node.js 服务端也都能用。对 GeoJSON 本身还不熟的小伙伴,可以先看看小编之前写的《「GIS教程」什么是GeoJSON》;GeoJSON 标准这几年也在演进,比如小编之前在《GeoJSON 发布新标准啦,JSON-FG 来了!》中分享过 OGC 推出的 JSON-FG 扩展。

切片产出的瓦片为矢量瓦片规范(MVT)的 JSON 版本,为了让渲染和交互更快,每个缩放级别都会做简化,只保留符合该级别精度的细节,形状会被简化,过小的多边形和折线会被过滤掉。关于矢量瓦片格式的演进,可以参考小编之前在《重磅!MVT的继任者来了?MapLibre正式发布MLT矢量瓦片格式》中介绍过,MapLibre 在 MVT 之后又推出了新一代 MLT 格式。

核心工作原理

从原理上说,geojson-vt 做的是索引一次、按需切片,内部由几个模块协作完成。

  • convert:把 GeoJSON 转成内部格式,同时做 Web Mercator 投影,统一到瓦片坐标空间。
  • simplify:用 Douglas-Peucker 算法按缩放级别简化几何,级别越低简化越狠。
  • clip:按瓦片边界裁剪几何,确保每个要素正确落到对应的瓦片里。
  • tile/transform:把处理好的几何组织成符合规范的瓦片对象,再做坐标换算。

关键在于按需切片。初始化时只构建到 indexMaxZoom(默认 5 级)的索引,更高的级别不做预计算,而是等前端请求某个 z/x/y 时才去切那一块。所以初始化很快,之后的瓦片请求基本都是毫秒级返回。数据更新时也不用重新发布瓦片,重新拉一次 GeoJSON 重建索引就行。

快速上手

安装:

npm install geojson-vt

基础用法:

import GeoJSONVT from 'geojson-vt';

const tileIndex = new GeoJSONVT(geoJSON);

// 请求某个瓦片
const features = tileIndex.getTile(z, x, y).features;

// 查看已生成的瓦片坐标
console.log(tileIndex.tileCoords); // [{z: 0, x: 0, y: 0}, ...]

getTile 在数据范围外会返回 null。如果追求零拷贝,可以用 getTileRaw 直接拿存储态的数据,返回扁平 [x, y, x, y, ...] 的类型化数组,每个环一个数组。

浏览器里也可以直接引 CDN:

<script src="https://unpkg.com/geojson-vt/geojson-vt.js"></script>
<script>
  const tileIndex = new GeoJSONVT(geoJSON);
</script>

常用参数

geojson-vt 提供了一批可调参数,默认值对大多数场景够用:

  • maxZoom:保留细节的最大缩放级别,默认 14,最高 24
  • tolerance:简化容差,数值越大简化越明显,默认 3
  • extent:瓦片范围(宽高),默认 4096
  • buffer:瓦片四周的缓冲区,默认 64,避免要素在瓦片边缘被切得太碎
  • indexMaxZoom:初始索引的最大级别,默认 5,之上按需生成
  • indexMaxPoints:索引中单个瓦片的最大点数,默认 100000
  • promoteId / generateId:要素 id 相关设置,两者不能同时用

如果想把所有瓦片一次性预生成,把 indexMaxZoom 和 maxZoom 设成一样,indexMaxPoints 设为 0,再从 tileCoords 里取瓦片坐标即可。

在主流框架中的应用

geojson-vt 的生态相当完整,MapLibre GL JS 里用它的维护版 @maplibre/geojson-vt 支持大 GeoJSON 数据源;OpenLayers 官方示例里有 geojson-vt 集成,配合 VectorSource 就能用;Leaflet 生态中也有依赖它的矢量瓦片插件(如 leaflet.vectorgrid),想要输出标准 MVT 二进制格式,可以和 vt-pbf 配合,在 Node.js 里做服务端动态发布。另外项目还有一个 C++11 移植版 geojson-vt-cpp,给非 JS 环境使用。

总结

之前做前端大 GeoJSON 渲染,如果走预切片,数据一更新瓦片就得重切,如果走后端服务,又要为单个数据源维护一套接口和并发。geojson-vt 把切片这步整个下沉到浏览器,索引建一次、按需出片,几十 KB 的行政区划到百万级点的点位数据都能在主流 WebGIS 框架里直接渲染,对做数据可视化和轻量 WebGIS 的小伙伴来说,是个上手成本很低的实用选择。

PS:需要注意它最多支持到 24 级缩放,超大数据首次构建索引也会花一点时间,建议放进 Web Worker 里。

参考

  1. geojson-vt GitHub 仓库:https://github.com/mapbox/geojson-vt/
  2. geojson-vt npm 页面:https://www.npmjs.com/package/geojson-vt
  3. MapLibre 的 geojson-vt 文档:http://maplibre.org/geojson-vt/
  4. OpenLayers geojson-vt 集成示例:https://openlayers.org/en/latest/examples/geojson-vt.html
  5. geojson-vt 终极指南:浏览器端动态 GeoJSON 矢量瓦片切片技术详解:https://blog.csdn.net/gitblog_00008/article/details/139108148

相关阅读

麻辣GIS-Sailor

作者:

GIS爱好者,学GIS,更爱玩GIS。

声明

1.本文所分享的所有需要用户下载使用的内容(包括但不限于软件、数据、图片)来自于网络或者麻辣GIS粉丝自行分享,版权归该下载资源的合法拥有者所有,如有侵权请第一时间联系本站删除。

2.下载内容仅限个人学习使用,请切勿用作商用等其他用途,否则后果自负。

手机阅读
公众号关注
知识星球
手机阅读
麻辣GIS微信公众号关注
最新GIS干货
关注麻辣GIS知识星球
私享圈子
没有下文

留言板(小编看到第一时间回复)