目录
这篇介绍的在 Awesome GIS 基本上都有,经过我的筛选,在 npmjs.com
上也都能找到,方便融入日益强大的 npm 生态。不过这些库大部分都保留了全局库的形式,在非框架中也能使用。有一部分是浏览器 + NodeJS 双端可用的。
如果只是完成 WKT
与 GeoJSON
这两个格式之间的转换,那么下面任意一个都能完成你的任务,选库体积最小的即可。否则,就按需选择,就个人体验而言,@terraformer/wkt
这个库比较均衡。
下面用表格对比这几个库。
wkt
@terraformer/wkt
wkt-parser-helper
@syncpoint/wkx
ts类型
无
有,额外安装
ts 源码
有
库大小
16.7 KB
86.8 KB
15.1 KB
69.7 KB
纯净度
0 依赖
0 依赖
1 依赖
1 依赖
丰富度
parse + stringify
parse + stringify
parse + stringify
丰富,还包括 WKB
API文档
有
有,详尽
有,详尽
有
更新
2019.11
2022.8
2022.8
2021.5
@syncpoint/wkx
是 wkx
这个库的改良版,主要是升级了一些过期的底层 API(适配 NodeJS)。
其实这些库的更新时间不必太在意,因为 WKT
这种规范已经发布多年,且足够简单,能用就行,主要是用得舒服。
库大小也并不是真正会包含在最终页面程序之中的大小,因为这些库有的用到 bundler,库大小是包含了多个文件的(例如不同模块风格的库文件、源程序文件等)。
GeoPackage
是一种基于 SQLite3 定义来的简易单文件地理数据存储格式,文件后缀名是 .gpkg
,可以被 QGIS、ArcGIS 读取,开源免费,支持扩展。
与 SpatialLite 均基于 SQLite3 是相似的,但是最大的不同是,SpatialLite 支持数据库的基本操作,而 GeoPackage 更像一种存粹仓库,不太像普通数据库一样能做查询。
pnpm add @ngageoint/geopackage
这里有一个使用这个库直接在页面读取 GeoPackage 文件中地理数据的网站 GeoPackage Viewer。
此外,这个 @ngageoint
账户下还有一堆比较积极维护的库:
@ngageoint/leaflet-geopackage
- Leaflet.js 的插件,允许把 gpkg 直接加载到 lf 地图中剩下的是一些 NodeJS 才能用的(浏览器不能用)格式转换库:
@ngageoint/geopackage-geojson-js
- NodeJS 端使用,GeoJSON 和 GeoPackage 互转@ngageoint/geopackage-xyz-js
- NodeJS 端使用,把 xyz 瓦片的 zip 包转为 GeoPackage@ngageoint/geopackage-pbf-js
- NodeJS 端使用,把 pbf 数据转为 GeoPackage@ngageoint/geopackage-mbtiles-js
- NodeJS 端使用,把 mbtiles 数据转为 GeoPackage@ngageoint/geopackage-csv-js
- NodeJS 端使用,把 csv 数据转为 GeoPackage@ngageoint/geopackage-shapefile-js
- NodeJS 端使用,把 shapefile zip 文件转为 GeoPackageShapefile 是 Esri 的杰作,是一种多文件的数据格式,虽然我在各种场合不遗余力地推荐大家使用新的数据格式,但是总是有一些人还在问前端能不能解析 Shapefile。这个库源代码使用 TypeScript 编写,打包后支持类型提示(自带 d.ts
)。
用于浏览器的打包库文件大约 100+ KB,可以接受。
pnpm add ts-shapefile
这个库的用法要到 GitHub 仓库看 README。
注意,Shapefile 规范本体并不含坐标系,所以本库不解析 .prj
文件中的坐标系信息。坐标系的操作库可以看本文第二节。
Mapbox 团队有一个用于写入 Shapefile 并下载为 zip 的库可供参考(纯 js,浏览器可用):shp-write
注意,部分 npm 上的 shapefile 库是 NodeJS 后端库,浏览器不可用,例如
shp2json
、shp-write-stream
、shp-stream
等
GIS 开发界 GDAL 可谓是祖师爷级别的库,它为多种空间数据格式提供了驱动程序(解析器),集成了一些简单的算法实现。
与 npm 上的 gdal 库不同,gdal
库是 NodeJS 对 GDAL 的接口绑定,是后端库,浏览器不可用。(p.s,gdal-async 解决了 gdal 库非异步的问题,然而浏览器还是用不了)。
这个 gdal3.js 使用 emscripten
把 GDAL 转成了 WebAssembly
,这样浏览器就能使用 GDAL 了,不过与绑定版本性能还是有所差异的。这个库的源码使用 TypeScript 编写。
pnpm add gdal3.js
由于支持了多种格式,携带的 WebAssembly 文件略多,这个库的体积也膨胀到了 38.4 MB
,浏览器真的想用请谨慎考虑。
文档很详尽,因为携带了 wasm 等额外文件,所以在打包环境使用也要注意文件的拷贝,很时髦地在文档中告知了 Webpack、Vite 环境的浏览器应用应该怎么做。
我在很多场合都表明:浏览器 + JavaScript 不应用于重度的数据转换,所以大部分重量级的格式转换应该由后端程序完成,其它语言(运行时)有更出色的实现,例如 C++、Java、C#.NET、Rustlang、NodeJS、Python 都有。
在浏览器端有时候是不得而为之。应付一些简单的格式转换还是能胜任的。
著名 C++ 投影库 PROJ
的 JavaScript 版本,ts 类型需要额外安装 @types/proj4
。
pnpm add proj4
这个库仅支持单个坐标的转换,对于复杂的数据格式投影转换,需要借助更高层级的封装库,见下文。
pnpm add gcoord
国人开发的专门解决 “火星”、“百度” 等加密算法的问题。坊间通常称他们 “火星坐标系”、“百度坐标系”,实际上只是一些非公开的加密算法,这个库能将加密后的坐标通过拟合的方式比较准确地纠正。
其官方文档指出支持坐标数组和 GeoJSON 的转换。
这个库并不是拿来做数据坐标系转换的,而是根据 WKID
取坐标系的 WKT 定义用的。
它没有 ts 定义,这是比较可惜的一点。它的默认查询模式需要联网,通过 epsg.io
在线 API 请求查询,所以在大陆环境可能有影响。
pnpm add spatialreference
用法举例:
import SR from 'spatialreference'
new SR({}).wkidToWkt(4326, (err, wkt) => {
if (!err) console.log(wkt)
})
这个库还支持在传入对象中添加数据库方面的数据,参考它的文档,允许从数据库中获取 WKT。
如果你没有在线环境,用不了 2.3 的库,那么可以使用 epsg
库获得坐标系的 PROJ4
定义。这个库自带了一个 JSON 字典。
pnpm add epsg
例子:
import epsg from 'epsg'
console.log(epsg['EPSG:3857'])
// +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs
这个库是 commonjs 模块,需要借助 bundle 转换。
这个与 2.3、2.4 就是相反的操作了。
pnpm add get-epsg-code
例子:
import getEPSGCode from 'get-epsg-code'
const proj4string = `+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs`
const wkid = getEPSGCode(proj4string)
// 3857
它的文档说支持几乎所有格式,WKT、proj4、esriproj 均可尝试:在线测试。
前者由 TypeScript 写成,在其 dist/
下的打包成果文件中,是将 proj4
打包进去了,所以体积会略大(因为 proj4
本身就有 900+KB),好处是 API、说明文档较齐全,也有类型提示,不过缺点是对 GeoJSON 没有使用定义,而是粗暴地设为 any
。
pnpm add reproj-helper
举例:
import RH from 'reproj-helper'
const pointFeature = {
"type": "Feature",
"properties": {},
"geometry": {
"coordinates": [
27.896140109578766,
20.219492193232625
],
"type": "Point"
}
}
const rp = new RH.ReProjector()
rp.from('4326')
rp.to('3857')
rp.feature(pointFeature)
const result = await rp.project()
后者就比较轻量化了,发布到 npmjs.com 上的包不含打包成果,但是在安装依赖时也会把 proj4
安装进来,专心于 GeoJSON 对象的转换,支持校验 GeoJSON 是否存在坐标系定义。这个就没有 ts 类型提示了:
pnpm add reproject
举例:
import { reproject } from 'reproject'
const pointFeature = {
"type": "Feature",
"properties": {},
"geometry": {
"coordinates": [
27.896140109578766,
20.219492193232625
],
"type": "Point"
}
}
console.log(reproject(
pointFeature,
'+proj=longlat +datum=WGS84 +no_defs +type=crs',
'+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs +type=crs'
))
JTS 有个 C++ 的儿子 GEOS
,然后又有个 JavaScript 的儿子 jsts
。JTS
是 Java 编写的几何库,其地位无需多言。
pnpm add jsts
pnpm add @types/jsts -D
之前写过一篇如何用它的文章,以缓冲分析为例:
import JSTSWKTReader from 'jsts/org/locationtech/jts/io/WKTReader'
import JSTSGeoJSONWriter from 'jsts/org/locationtech/jts/io/GeoJSONWriter'
import JSTSBufferOp from 'jsts/org/locationtech/jts/operation/buffer/BufferOp'
const wkt = `POINT (0 0)`
const bufferCenter = new JSTSWKTReader().read(wkt)
const bufferResult = JSTSBufferOp.bufferOp(
bufferCenter,
10
) // instanceof Geometry
const bufferResultGeoJSON = new JSTSGeoJSONWriter().write(bufferResult)
如果不熟悉其包结构和 JTS 的用法,我不是很推荐直接上手使用 jsts。
上文介绍 WKT 库时这个 @terraformer
账号有出现。这个库可以简易地对 GeoJSON 对象进行简单的空间分析,可以说是一个简单版本的 turf:
pnpm add @terraformer/spatial
它的类型库需要额外安装 @types/terraformer__spatial -D
。
它具备 applyConverter
(GeoJSON 要素顶点遍历器)、intersects
、convexHull
、contains
等非常简单的分析功能,见其 README 文档。
接下来这些几何库的 “GIS” 血缘就比较淡了,不过辅助用用也还是可以的。
类型提示
库大小
丰富度
文档
用途建议
earcut
额外安装
95.2 KB
专一功能
齐备
离散几何多边形的三角化,生成三角网格
hextile
无
小于 50KB
专一功能
基本齐全
生成渔网(支持若干种内置形状)
geometric
额外安装
107 KB
中等
齐备
简单几何运算,替代部分 turf 需求
@flatten-js/core
ts 源码
5.68 MB
丰富
完善
应对较为复杂几何图形的几何计算
geometry-extrude
ts 源码
288 KB
专一功能
齐备
挤出 polygon 成体,并三角化;基于 earcut
simplepolygon
无
36.6 KB
专一功能
齐备
处理 GeoJSON。将复杂的(即自交的)GeoJSON 多边形,分解为复合的简单、非自交的单环多边形。见 README
其实上述这些库还远远不够,开源社区总能找到宝藏,不过应该也足够使用了。我为什么没有把 turf
列出来呢?是因为 turf 的算法准确性、性能实在是拿不出手,群友们都反馈过这个问题,能不用还是尽量不要用了。
而且,复杂的几何计算我觉得还是交给后台计算程序比较好,前端能运算的终究有限。
这个库是前端几个地图库(支持 OpenLayers V7、Leaflet.js V1.9、MapboxGL V2、Maplibre V2、GoogleMapAPI V3)的插件,由 TypeScript 写成,文档齐全,也有在线例子。
pnpm add terra-draw
在我写这篇文章时,它还在 alpha 阶段,不过可用性已经很不错了。官方示例指路:TerraDraw
如题。这个绘图插件很强大,基本满足绝大多数 2D 绘制要求,体积也来到了 450 KB+。
pnpm add @geoman-io/leaflet-geoman-free
由 TypeScript 编写,支持多国语言,具有十分完善的文档。不过,它自带的按钮对于某些场景可能不太合适使用了(想自定义按钮样式、UI 逻辑的情况)。总体来说我打 98 分。
这个像个字典,小型项目(不具备数据库接口调用条件)适合使用。
pnpm add china-region
另有带类型提示的版本 china-regions-ts
,不过我个人建议在找这类行政编码库时,尽量找最新版的。
这个可以替代 GeoJSON 各级对象在你 TypeScript 项目中的 any
问题,注意要安装到开发依赖,这东西只是个类型库。
pnpm add @types/geojson -D
用法简单:
import type { Polygon } from 'geojson'
// ...
OGC API 是什么我之前写过一篇入门介绍,是 OGC 正在开发推进的下一代 GIS 网络规范,涵盖方方面面。其中,OGC Feature API
就是 WFS
的下一代规范,也即原来打算的 WFS 3.0
。
当满足 OGC Feature API 的服务启动后,可以用这个包来调用 OGC Feature API
规范定义的功能。
当前 OGC API 仍未完全落定,以最新版为准,可以关注
@ogcapi-js
这个账户下的新包。
pnpm add @ogcapi-js/features
用法也很简单。
import { Service } from `@ogcapi-js/features`;
// 创建一个服务对象
const service = new Service({
baseUrl: 'https://ogcapi.service.com'
});
// 调用接口获取数据集清单
const collections = await services.getCollections();
Esri 用户的小工具,不过也适用于部分需要坐标系 WKT 的场景,暴露一个 lookup 函数,传入 WKID 来查找坐标系对象:
pnpm add @esri/proj-codes
这个包略大,如无必要则不用,查找坐标系的工作应该让后端数据库完成。
import codes from '@esri/proj-codes'
const crs = codes.lookup(3857)
crs.name
// 'WGS_1984_Web_Mercator_Auxiliary_Sphere'
crs.wkt
// 'PROJCS["WGS_1984_Web_Mercator_Auxiliary_Sphere",GEOGCS["GCS_WGS_1984"...'
crs.description
// 'WGS 1984 Web Mercator Major Auxiliary Sphere'
crs.authority
// 'EPSG'
crs.deprecated
// 'no'
crs.extent
// { "slat": -85.06, "nlat": 85.06, "llon": -180.0, "rlon": 180.0 }
// this works too
codes.lookup(3857).name
// 'WGS_1984_Web_Mercator_Auxiliary_Sphere'
这篇主要以浏览器前端为主,其实有一部分库在 NodeJS 后端也能用,譬如坐标系、格式转换、几何空间分析等。单独给后端 NodeJS 的也有,数据库、格式转换、图像算法的偏多,不过也逐渐淡去了 GIS 血缘,有机会再介绍吧。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章