Skip to content

MapLibre 适配器(@geoverse/editor-libre)

MapLibre GL JS 是纯渲染库、无内置编辑@geoverse/editor-libre 采用自绘范式:把要素、顶点句柄、变换手柄、绘制草图分别渲染成 GeoJSON source + 图层,自接 mousedown/mousemove/mouseup 等鼠标手势,归一成 editor-core 的命令——与 OpenLayers 适配器 共用同一引擎、同一命令、同一手感。

它接收一个 maplibre Map@geoverse/core-libreGMap 继承自 maplibre Map,可直接传入)。

为什么自绘,而非接入 Terra Draw / mapbox-gl-draw?

那些库自带 feature store,会与本架构「EditEngine 为唯一真源」冲突(需双 store 同步)。自绘让引擎保持唯一真源、两轨手感一致。详见仓库 docs/adr/0005

安装

shell
pnpm add @geoverse/editor-core @geoverse/editor-libre @geoverse/core-libre maplibre-gl

上手

ts
import { GMap } from '@geoverse/core-libre';
import { EditSession } from '@geoverse/editor-core';
import { LibreEditorAdapter } from '@geoverse/editor-libre';
import 'maplibre-gl/dist/maplibre-gl.css';

const map = new GMap({
  container: 'map',
  base: 'carto-light',
  center: [118.15, 24.56],
  zoom: 14,
});

const session = new EditSession({ crs: 'EPSG:4326', features: seed }); // seed 用经纬度
const adapter = new LibreEditorAdapter(map, {
  onSelect: (id, additive) => {
    if (id) session.select([id], additive);
    else if (!additive) session.clearSelection();
    adapter.setSelection(session.getSelected());
  },
});

session.attach(adapter);
adapter.setMode('select');

工作 CRS = EPSG:4326(度)

MapLibre 的 GeoJSON source 即 lng/lat,故 libre 轨工作 CRS 固定为 EPSG:4326seed 坐标用经纬度。偏移/缩放的“距离”单位为(非米),高纬度有形变;米制度量换算列入后续。

工具模式(adapter.setMode(mode)

模式集合与 OL 适配器一致:select / move / transform / modify / add-vertex / delete-vertex / split / split-polygon / merge / draw-point / draw-line / draw-polygon,归一到同一批命令。

绘制与按线拆面的收尾手势与 OL 略有差异(自绘):

能力OL 轨MapLibre 轨(自绘)
绘制线/面ol/Draw 双击结束逐点单击、双击结束,带橡皮筋预览;收尾去重相邻点
面拆分Draw 折线在选中面上逐点单击画切割线、双击结束
顶点编辑ol/Modify拖自绘顶点句柄 → MoveVertexCommand
选中高亮feature 样式MapLibre feature-state + paint 表达式
变换手柄ol/Pointer自绘 handles source + 拖拽

双击结束时适配器会临时禁用 doubleClickZoom,避免与地图双击缩放冲突。

顶点句柄显示

与 OL 轨一致,句柄按模式 + 选择集分三档(详见核心概念 · 顶点句柄显示):modify / add-vertex / delete-vertex 为实心可编辑句柄,select / move / transform 为更小更淡的「幽灵」句柄(自绘 paint 切换 circle-radius/透明度),绘制/拆分/合并不显示。句柄坐标用 editor-core 共用的 collectVertexHandles。整体平移/变换拖拽期间隐藏;顶点拖拽(modify)时自绘句柄随之移动。

非模式操作

与 OL 轨相同:镜像、偏移、点/面合并、多点拆分、复制粘贴由应用层对选择集直接派发命令(命令也从 @geoverse/editor-libre 转出):

ts
import { MirrorCommand, OffsetCommand } from '@geoverse/editor-libre';

const sel = session.getSelected();
session.engine.dispatch(new MirrorCommand(sel, 'vertical'));
session.engine.dispatch(new OffsetCommand(sel[0], 0.0004)); // 度

面/多面运算与 OL 轨一致(命令通用,仅 CRS 单位不同):MergePolygonsCommand(不相邻 → MultiPolygon)、SplitMultiPolygonCommand(多面 → 多个面)、DifferencePolygonsCommand(布尔 A−B)、PunchHoleCommand(结构挖洞,B 作为 A 内环、须在 A 内部)、FillHoleCommand(填洞,移除内环,挖洞的逆操作)。差集是布尔运算(B 跨界切缺口),挖洞是结构插入内环(保留 A 外边界)。

面开洞 / 消洞(「非分离切」,命令与 OL 轨通用,仅工作 CRS 为 4326、坐标与宽度以度计;缺省宽度按面 bbox 对角线 0.5% 自适应,可 { width } 覆写)。**open-hole(线驱动,自绘模式)**选中含洞面→逐点画切割线、双击结束,把「从外边界进入某洞、不贯穿到对侧」的切割线所连通的洞连到外边界成凹湾(面仍 1 块、少一内环);**消洞 CloseHoleCommand(id)(一键,无需交互)**用凸包自动求出面上所有凹湾并封回内环洞,是开洞的逆向能力、与面填洞对称——直接 dispatch 即可,不用画线也不用点选。外边界为凸、无凹湾时报 CLOSE_HOLE_NO_BAY(普通带洞面只想去洞请用 FillHoleCommand)。

线/多线运算:MergeLinesCommand(端点相接 → 单线)、CombineLinesCommand(不要求相接 → MultiLineString)、SplitMultiLineStringCommand(多线 → 多条线)。

吸附

拖动顶点或绘制时,落点会自动吸附到既有要素的顶点与边。自绘适配器复用 @geoverse/editor-coreSnapIndex(与 OL 版同一吸附内核,手感一致);顶点拖拽会排除被拖要素自身,避免吸回原位。命中吸附点时该处显示橙色高亮环,光标也按模式(拖顶点 grab、选择 pointer、绘制 crosshair 等)给出可操作提示。默认开启,可配置或运行时切换:

ts
const adapter = new LibreEditorAdapter(map, { snap: true, snapTolerance: 10 });
adapter.setSnap(false); // 运行时关闭

下一步

在线示例:仓库 examples/editor-libre/pnpm dev:examples/editor-libre/)。