目錄
- 前置說明
- 1. 與資料格式轉換決議相關
- 1.1. 決議和轉換 WKT 幾何資料
- 1.2. 前端直接讀取 GeoPackage -
@ngageoint/geopackage - 1.3. 前端直接讀取 Esri Shapefile -
ts-shapefile - 1.4. 把 GDAL 搬進瀏覽器 -
gdal3.js - 1.5. 格式庫小結
- 2. 操作空間坐標系
- 2.1. 重投影
proj4 - 2.2. 糾“火星”、“百度”加密坐標
- 2.3. 空間坐標系的 WKT 定義 -
spatialreference - 2.4. 空間坐標系的 PROJ 定義 -
epsg - 2.5. 從坐標系定義字串推導 WKID -
get-epsg-code - 2.6. 對 GeoJSON 的重投影 -
reproj-helper、reproject
- 2.1. 重投影
- 3. 簡易空間分析與幾何運算
- 3.1. JTS 的移植 -
jsts - 3.2. 給 GeoJSON 設計的簡易版 “turf” -
@terraformer/spatial - 3.3. 其他一些幾何圖形變換與計算庫
- 3.4. 幾何空間分析庫小結
- 3.1. JTS 的移植 -
- 4. 地圖庫擴展
- 4.1. 為 ol、mapboxgl、leaflet.js 擴展繪圖工具 -
terra-draw - 4.2. 為 leaflet.js 擴展的繪圖工具
- 4.1. 為 ol、mapboxgl、leaflet.js 擴展繪圖工具 -
- 5. 雜項
- 5.1. 中國大陸行政區劃編碼庫
- 5.2. 為 GeoJSON 增強型別提示 -
@types/geojson - 5.3. 與 WFS 類似的 OGC Feature API 客戶端實作庫 -
@ogcapi-js/features - 5.4. 操作 Esri 的投影定義物件
- 6. 小結
前置說明
這篇介紹的在 Awesome GIS 基本上都有,經過我的篩選,在 npmjs.com 上也都能找到,方便融入日益強大的 npm 生態,不過這些庫大部分都保留了全域庫的形式,在非框架中也能使用,有一部分是瀏覽器 + NodeJS 雙端可用的,
1. 與資料格式轉換決議相關
1.1. 決議和轉換 WKT 幾何資料
如果只是完成 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,庫大小是包含了多個檔案的(例如不同模塊風格的庫檔案、源程式檔案等),
1.2. 前端直接讀取 GeoPackage - @ngageoint/geopackage
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 檔案轉為 GeoPackage
1.3. 前端直接讀取 Esri Shapefile - ts-shapefile
Shapefile 是 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等
1.4. 把 GDAL 搬進瀏覽器 - gdal3.js
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 環境的瀏覽器應用應該怎么做,
1.5. 格式庫小結
我在很多場合都表明:瀏覽器 + JavaScript 不應用于重度的資料轉換,所以大部分重量級的格式轉換應該由后端程式完成,其它語言(運行時)有更出色的實作,例如 C++、Java、C#.NET、Rustlang、NodeJS、Python 都有,
在瀏覽器端有時候是不得而為之,應付一些簡單的格式轉換還是能勝任的,
2. 操作空間坐標系
2.1. 重投影 proj4
著名 C++ 投影庫 PROJ 的 JavaScript 版本,ts 型別需要額外安裝 @types/proj4,
pnpm add proj4
這個庫僅支持單個坐標的轉換,對于復雜的資料格式投影轉換,需要借助更高層級的封裝庫,見下文,
2.2. 糾“火星”、“百度”加密坐標
pnpm add gcoord
國人開發的專門解決 “火星”、“百度” 等加密演算法的問題,坊間通常稱他們 “火星坐標系”、“百度坐標系”,實際上只是一些非公開的加密演算法,這個庫能將加密后的坐標通過擬合的方式比較準確地糾正,
其官方檔案指出支持坐標陣列和 GeoJSON 的轉換,
2.3. 空間坐標系的 WKT 定義 - spatialreference
這個庫并不是拿來做資料坐標系轉換的,而是根據 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.4. 空間坐標系的 PROJ 定義 - epsg
如果你沒有在線環境,用不了 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.5. 從坐標系定義字串推導 WKID - get-epsg-code
這個與 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 均可嘗試:在線測驗,
2.6. 對 GeoJSON 的重投影 - reproj-helper、reproject
前者由 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'
))
3. 簡易空間分析與幾何運算
3.1. JTS 的移植 - jsts
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,
3.2. 給 GeoJSON 設計的簡易版 “turf” - @terraformer/spatial
上文介紹 WKT 庫時這個 @terraformer 賬號有出現,這個庫可以簡易地對 GeoJSON 物件進行簡單的空間分析,可以說是一個簡單版本的 turf:
pnpm add @terraformer/spatial
它的型別庫需要額外安裝 @types/terraformer__spatial -D,
它具備 applyConverter(GeoJSON 要素頂點遍歷器)、intersects、convexHull、contains 等非常簡單的分析功能,見其 README 檔案,
3.3. 其他一些幾何圖形變換與計算庫
接下來這些幾何庫的 “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 |
3.4. 幾何空間分析庫小結
其實上述這些庫還遠遠不夠,開源社區總能找到寶藏,不過應該也足夠使用了,我為什么沒有把 turf 列出來呢?是因為 turf 的演算法準確性、性能實在是拿不出手,群友們都反饋過這個問題,能不用還是盡量不要用了,
而且,復雜的幾何計算我覺得還是交給后臺計算程式比較好,前端能運算的終究有限,
4. 地圖庫擴展
4.1. 為 ol、mapboxgl、leaflet.js 擴展繪圖工具 - terra-draw
這個庫是前端幾個地圖庫(支持 OpenLayers V7、Leaflet.js V1.9、MapboxGL V2、Maplibre V2、GoogleMapAPI V3)的插件,由 TypeScript 寫成,檔案齊全,也有在線例子,
pnpm add terra-draw
在我寫這篇文章時,它還在 alpha 階段,不過可用性已經很不錯了,官方示例指路:TerraDraw
4.2. 為 leaflet.js 擴展的繪圖工具
如題,這個繪圖插件很強大,基本滿足絕大多數 2D 繪制要求,體積也來到了 450 KB+,
pnpm add @geoman-io/leaflet-geoman-free
由 TypeScript 撰寫,支持多國語言,具有十分完善的檔案,不過,它自帶的按鈕對于某些場景可能不太合適使用了(想自定義按鈕樣式、UI 邏輯的情況),總體來說我打 98 分,
5. 雜項
5.1. 中國大陸行政區劃編碼庫
這個像個字典,小型專案(不具備資料庫介面呼叫條件)適合使用,
pnpm add china-region
另有帶型別提示的版本 china-regions-ts,不過我個人建議在找這類行政編碼庫時,盡量找最新版的,
5.2. 為 GeoJSON 增強型別提示 - @types/geojson
這個可以替代 GeoJSON 各級物件在你 TypeScript 專案中的 any 問題,注意要安裝到開發依賴,這東西只是個型別庫,
pnpm add @types/geojson -D
用法簡單:
import type { Polygon } from 'geojson'
// ...
5.3. 與 WFS 類似的 OGC Feature API 客戶端實作庫 - @ogcapi-js/features
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();
5.4. 操作 Esri 的投影定義物件
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'
6. 小結
這篇主要以瀏覽器前端為主,其實有一部分庫在 NodeJS 后端也能用,譬如坐標系、格式轉換、幾何空間分析等,單獨給后端 NodeJS 的也有,資料庫、格式轉換、影像演算法的偏多,不過也逐漸淡去了 GIS 血緣,有機會再介紹吧,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/543104.html
標籤:其他
上一篇:淺談瀏覽器端 WebGIS 開發可能會用到的、提升效率的 js 庫
下一篇:什么是WMS系統?
