GeoLibre:完全运行在浏览器里的开源云原生 GIS 平台

GeoLibre 3D Tiles 演示

GitHub Trending 上周出现了一个增长速度异常的项目:opengeos/GeoLibre,一个完全免费开源的云原生 GIS 平台,上线不到两个月已获得 2600+ Star,日均新增 400+。它在 Reddit r/gis 社区获得了 178 个赞,开发者 Qiusheng Wu(吴秋生)是地理空间 Python 生态中最活跃的贡献者之一,其此前作品 geehtml、leafmap、geemap 累计 GitHub Star 超过 4000。

GeoLibre 的定位很明确:用一套代码同时覆盖浏览器、桌面(Tauri v2)、Android 原生应用和 Jupyter Notebook 四个平台,全部数据本地处理,无需账号、无需服务器。它构建在 MapLibre GL JS、DuckDB-WASM Spatial、deck.gl 和 Tauri v2 之上,对标的是 Google Earth Pro 和 ArcGIS Online,但运行成本为零。

架构:一套 monorepo,四个平台

GeoLibre NYC 建筑 3D 可视化

GeoLibre 采用 npm workspaces monorepo 结构,核心包分工明确:

职责
@geolibre/core领域类型、项目 JSON Schema、全局状态(Zustand)
@geolibre/mapMapLibre 生命周期、图层同步、GeoJSON/栅格/瓦片处理
@geolibre/ui共享 UI 组件(shadcn 风格)
@geolibre/processing客户端算法注册表
@geolibre/plugins插件接口及内置插件
geolibre-desktopShell 布局、Tauri I/O、组合层

状态流的设计是一个亮点。用户添加数据后,本地矢量数据直接解析或通过 DuckDB-WASM Spatial 转为 GeoJSON,传递给 store 的 addGeoJsonLayer。瓦片、服务、栅格、ArcGIS、MBTiles 等图层创建 GeoLibreLayer 记录,携带源元数据和原生 MapLibre 图层 ID。MapCanvas 订阅 layersMapController.syncLayers 更新 MapLibre 的 sources 和 layers,保持图层控制同步。

这种设计的关键在于 store 是引擎无关的:它持有的是纯 GeoLibreLayer 记录和 MapViewState,而非 MapLibre 对象。这使得后续接入 CesiumJS 3D 地球视图时,第二个渲染器只需订阅同一个 store 即可,无需任何引擎抽象层。

DuckDB-WASM:浏览器里的空间数据库

GeoLibre 最具技术深度的部分是将 DuckDB 的 Spatial 扩展编译为 WebAssembly,在浏览器内完成矢量文件的格式转换。工作流程如下:

sql
INSTALL spatial;
LOAD spatial;

GeoParquet 通过 DuckDB 的 Parquet reader 读取后加载 Spatial 扩展。其他本地矢量格式由 Spatial 的 ST_Read 函数处理(依赖 GDAL 支持的读取器)。压缩的 Shapefile 先用 shpjs 解析,失败后回退到 DuckDB Spatial。KML 文件由自研解析器处理,保留嵌入的符号样式,输出符合 simplestyle-spec 的属性(fillstrokestroke-width),使带样式的 KML 在渲染时与 Google Earth 中显示一致。

这意味着用户在浏览器里拖入一个 Shapefile 或 GeoPackage,不需要任何后端服务,DuckDB-WASM 就能在客户端完成空间查询和格式转换。

3D 地球视图:MapLibre 与 CesiumJS 的双引擎协同

GeoLibre 火星全球视图

GeoLibre 的 2D MapLibre 地图可以与 CesiumJS 渲染的 3D 地球并排显示,作为分屏面板而非全局引擎替换。实现上有几个关键工程决策:

延迟加载:Cesium 引擎约 4.8 MB,仅在面板切换到地球视图时通过动态 import() 加载,单独构建为独立 chunk,不影响 2D 启动路径。

相机同步packages/map/src/cesium-camera.ts 负责在 MapLibre 的 Web 墨卡托 MapViewState(zoom、天底角俯仰 pitch、方位 bearing)与 Cesium 的相机参数(米制距离 range、地平线角俯仰、航向 heading)之间转换。匹配基准是地面分辨率(每像素米数),确保两个面板的屏幕比例尺保持同步,即使面板高度不同。CesiumCanvas 从共享的 mapView 初始化相机,双向写入相机移动,并带有容差检查以消除应用→moveEnd 的回声循环。

图层同步CesiumLayerSync 将 store 中的 GeoLibreLayer[] 映射到地球视图上,复用与 MapController.syncLayers 相同的分面板可见性覆盖逻辑。它渲染 Cesium 擅长的图层类型:GeoJSON(作为 draped GeoJsonDataSource,从图层的填充/描边/透明度参数读取样式)、XYZ/栅格/WMTS/WMS(作为 ImageryLayer)和 3D Tiles(作为 Cesium3DTileset 图元)。其他图层类型(PMTiles、MBTiles、Zarr、LiDAR、高斯泼溅、deck.gl 可视化)在地球视图中跳过,仅在 2D 面板中渲染。

行星地图:不止于地球

GeoLibre 不局限于地球。通过 OpenPlanetaryMap 和 USGS 天体地质学数据,它覆盖了月球、火星、水星、金星、木星的伽利略卫星(木卫一、木卫二、木卫三、木卫四)、土卫六、冥王星和冥卫一。每个项目配置独立的椭球体参数,其半径驱动距离、面积和比例尺测量,确保你在绘制火星地图时的测量数据是基于火星的参数计算的,而非地球的。

处理引擎:三选一的矢量分析

GeoLibre 的矢量分析工具有三种执行引擎:

  1. Turf.js(客户端):Processing → Vector 菜单下的工具使用 Turf.js,无需任何后端
  2. GeoPandas/Shapely(Python sidecar):通过 FastAPI 管理的本地 sidecar 运行,提供投影感知的结果
  3. GeoPandas via Pyodide(浏览器内):将同一份 GeoPandas/Shapely 代码通过 Pyodide(编译为 WebAssembly 的 CPython)在浏览器中运行

第三种引擎的巧妙之处在于代码复用:几何逻辑模块 backend/geolibre_server/geolibre_server/vector_ops.py 同时被 sidecar 和浏览器运行。一个 Vite 插件将该模块复制到应用 bundle 中,一个 Web Worker 从 CDN 加载 Pyodide,安装 geopandas,并通过 JSON 字符串边界调用 run_vector_tool。单一代码源意味着 Sidecar 和 Pyodide 引擎返回完全一致的结果。

SQL Workspace 同样支持三种引擎:DuckDB、PostGIS(通过 PGlite)和 Apache Sedona。在桌面端,Sedona 运行在 SedonaDB(单节点 Rust 引擎,基于 DataFusion + Arrow)上;在浏览器中,它通过 CereusDB(SedonaDB 的 WebAssembly 构建)完全在客户端运行。

离线支持:PWA 的缓存策略

独立 Web 版本是一个可安装的 PWA。缓存策略分三层:

  • 预缓存(App Shell):HTML 和启动地图所需的 JS/CSS chunk 在首次访问后被预缓存,之后无需网络即可加载
  • 运行时缓存(CacheFirst):构建产物中内容哈希命名的资源(MapLibre bundle、DuckDB-WASM 及其 spatial 扩展、MapLibre feature-plugin chunks)在首次使用时缓存。文件名哈希使 CacheFirst 安全可靠:重新部署生成新 URL,永远不会将过期缓存当作当前版本
  • 底图缓存:来自 CORS 友好的默认主机(OpenFreeMap、CARTO)的瓦片和样式被运行时缓存

这套设计使得本地文件工作流(DuckDB Spatial 转换)在首次在线使用后可以离线运行。

安装方式

GeoLibre 的分发渠道覆盖全面:

  • Web:直接访问 web.geolibre.app,无需安装
  • 桌面:Windows、macOS、Linux 安装包,通过 geolibre.app/downloads/ 获取
  • Windows:上架 Microsoft Store
  • Arch Linux:AUR 包 geolibre-bin
  • Flatpak:FlatHub 上架 app.geolibre.GeoLibre
  • Dockerghcr.io/opengeos/geolibre,容器内捆绑 Python sidecar
  • Python/Jupyterpip install geolibreconda install -c conda-forge geolibre

数据源支持

GeoLibre v2.3 支持的数据源包括:XYZ 瓦片、WMS、WFS、矢量文件(GeoJSON、Shapefile、GeoPackage、GeoParquet)、矢量瓦片源、分隔文本、栅格瓦片模板、COG 和 GeoTIFF 栅格、MBTiles、ArcGIS FeatureServer/VectorTileServer、GPX 航点/轨迹/路线、3D Tiles、PMTiles、FlatGeobuf、Zarr、LiDAR 点云、高斯泼溅(Gaussian splats)。

此外还有通过插件提供的数据源:Microsoft Planetary Computer、Google Earth Engine、Overture Maps、联邦 Web Services(USDA、NOAA 等)。Time Slider 插件支持时间序列栅格和矢量数据的动画播放(COG、XYZ/WMTS、WMS-Time、时间过滤 GeoJSON)。

开源生态定位

GeoLibre 出现在 GIS 软件生态的一个重要变化节点。商业 GIS 软件 ArcGIS Online 的年订阅费用从数百到数千美元不等,且核心数据需要上传到 Esri 的云服务。Google Earth Pro 虽然免费但不开源、不支持自定义分析。QGIS 是成熟的开源桌面 GIS,但基于 Qt/C++ 技术栈,不具备 Web 原生能力和云原生数据处理能力。

GeoLibre 选择的技术栈(WebGPU、WebAudio、Web Workers、WebAssembly、WebSocket)让它从第一天就具备了浏览器原生的优势。所有计算在客户端完成,数据不离开用户设备。对于需要处理敏感地理空间数据的场景(国防、企业内部数据、个人隐私数据),这个架构特点具有实际意义。

项目作者 Qiusheng Wu 在地理空间 Python 生态的长期投入(Tennessee 大学研究教授,geehtml/leafmap/geemap/whiteboxgui 作者)为项目的持续维护提供了可信度。GeoLibre 采用 MIT 许可证,接受社区贡献,已有外部开发者提交的 issue 报告、反馈和功能改进。

来源: