Appearance
编辑器概览(@geoverse/editor-*)
GeoVerse 的要素编辑能力由三个相互独立的包组成:一个框架无关的编辑引擎,加两个分别接入 OpenLayers 与 MapLibre 的适配器。
@geoverse/editor-core 纯 TS 引擎(撤销重做 / 命令 / 校验 / 吸附 / 后端同步)——不依赖任何地图库
├──► @geoverse/editor-ol OpenLayers 适配器(peer: geoverse、ol)
└──► @geoverse/editor-libre MapLibre 适配器(peer: @geoverse/core-libre、maplibre-gl)| 包 | 作用 | peerDependencies |
|---|---|---|
@geoverse/editor-core | 编辑引擎与全部命令、几何运算、校验、吸附、后端同步。禁止 import 任何地图库(由 lint 强制)。 | 无(仅运行时 deps:@turf/*、jsts、rbush、nanoid) |
@geoverse/editor-ol | 把 ol/interaction(Draw/Modify/Translate/Pointer)归一成引擎命令。 | geoverse、ol、@geoverse/editor-core |
@geoverse/editor-libre | MapLibre 无内置编辑,适配器自绘顶点/手柄并接管鼠标手势。 | @geoverse/core-libre、maplibre-gl、@geoverse/editor-core |
实验性(0.1.0)
编辑器三包当前为 0.1.0,公共 API 可能在正式发布前微调。生产使用建议锁定版本并关注变更说明。
能力矩阵
创建 / 修改 / 节点编辑 / 拆分 / 合并 / 面·线运算 × 点(Point)/ 线(Line)/ 面(Polygon),全部经统一的命令与类型校验落地:
| 分类 | 能力 | 点 | 线 | 面 | 命令 |
|---|---|---|---|---|---|
| 创建 | 绘制 | ✓ | ✓ | ✓ | AddFeatureCommand |
| 创建 | 复制 / 粘贴 | ✓ | ✓ | ✓ | EditSession.copy() / AddFeaturesCommand |
| 修改 | 移动 | ✓ | ✓ | ✓ | TranslateCommand |
| 修改 | 旋转 / 缩放 / 镜像 | ✓ | ✓ | ✓ | RotateCommand / ScaleCommand / MirrorCommand |
| 修改 | 偏移复制 | ✓ | ✓ | OffsetCommand | |
| 节点 | 增 / 删 / 移动节点 | ✓ | ✓ | AddVertexCommand / DeleteVertexCommand / MoveVertexCommand | |
| 拆分 | 点拆分多点 | ✓ | SplitMultiPointCommand | ||
| 拆分 | 线打断 | ✓ | SplitLineCommand | ||
| 拆分 | 按线拆面 | ✓ | SplitPolygonByLineCommand | ||
| 拆分 | 多线 / 多面拆分 | ✓ | ✓ | SplitMultiLineStringCommand / SplitMultiPolygonCommand | |
| 合并 | 点合并 | ✓ | MergePointsCommand | ||
| 合并 | 线合并(端点相接) | ✓ | MergeLinesCommand | ||
| 合并 | 线组合(→ 多线) | ✓ | CombineLinesCommand | ||
| 合并 | 面合并(并集) | ✓ | MergePolygonsCommand | ||
| 面运算 | 差集(A−B) | ✓ | DifferencePolygonsCommand | ||
| 面运算 | 挖洞 / 填洞 | ✓ | PunchHoleCommand / FillHoleCommand | ||
| 面运算 | 开洞 / 消洞 | ✓ | ✓ | OpenHoleCommand(线驱动,适配器 open-hole 模式画切割线) / CloseHoleCommand(一键封上所有凹湾,无需交互) |
外加贯穿全部操作的撤销/重做与类型校验(不适用的几何类型会被命令拦截)。详见核心概念。
差集 vs 挖洞:差集是布尔运算(B 跨边界会切缺口、完全在内则成洞);挖洞是结构插入内环(精确保留外边界,要求 B 完全落在 A 内部),与填洞互为逆操作。差集 / 挖洞均为「选 2 个面、第一个为目标 A」的二元运算。各轨命令与坐标单位差异见 OpenLayers 适配器(米)/ MapLibre 适配器(度)。
开洞 / 消洞(「非分离切」,一对互逆操作):与上面几个都不同——**开洞(线驱动)**是一条切割线从外边界进入某个内环(洞),把洞经一条细通道连到外边界成「凹湾」(洞环并入外环,面仍是 1 块、少一个内环);**消洞(一键,无需交互)把外边界的所有凹湾(缺口)**自动封回内环洞,与「面填洞」对称(填洞去掉所有内环、消洞封上所有凹湾),是开洞的逆向能力。区别于「按线拆面」(须贯穿外环、切成 2 块)与「挖洞/填洞」(结构插入/移除内环)。消洞用凸包自动定出全部凹湾,无需点选位置;面上没有凹湾(外边界为凸,如普通带洞面)时明确拒绝——那种情况若只是想去掉洞请用「面填洞」。通道宽度按面 bbox 对角线 0.5% 自适应(可
{ width }覆写),结果是合法的单面。
安装
OpenLayers 轨:
shell
pnpm add @geoverse/editor-core @geoverse/editor-ol geoverse olMapLibre 轨:
shell
pnpm add @geoverse/editor-core @geoverse/editor-libre @geoverse/core-libre maplibre-gl5 分钟上手(OpenLayers)
ts
import { GMap } from '@geoverse/core-ol';
import { EditSession, SplitLineCommand } from '@geoverse/editor-core';
import { OlEditorAdapter } from '@geoverse/editor-ol';
const map = new GMap({
target: 'map',
base: 'gd-vec',
center: [118.18, 24.49],
zoom: 15,
});
const crs = map.getView().getProjection().getCode(); // 工作 CRS = 视图投影(默认 EPSG:3857)
const session = new EditSession({
crs,
features: [
{
id: 'l1',
geometry: {
type: 'LineString',
coordinates: [
/* …投影坐标… */
],
},
properties: {},
},
],
});
const adapter = new OlEditorAdapter(map, {
crs,
onSelect: (id, additive) => {
if (id) session.select([id], additive);
else if (!additive) session.clearSelection();
adapter.setSelection(session.getSelected());
},
});
session.attach(adapter); // 绑定交互 + 订阅渲染,返回解绑函数
adapter.setMode('select'); // 切换工具模式
// 撤销 / 重做
session.engine.undo();
session.engine.redo();5 分钟上手(MapLibre)
ts
import { GMap } from '@geoverse/core-libre';
import { EditSession } from '@geoverse/editor-core';
import { LibreEditorAdapter } from '@geoverse/editor-libre';
const map = new GMap({
container: 'map',
base: 'carto-light',
center: [118.15, 24.56],
zoom: 14,
});
const session = new EditSession({ crs: 'EPSG:4326' }); // MapLibre 的 GeoJSON 即 lng/lat
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');与 FeatureEditor 的区别
geoverse 内置的 FeatureEditor 只做基础顶点拖拽编辑(单要素、无撤销/打断/合并/拓扑/后端)。需要工程级编辑(撤销重做、打断合并、变换、节点增删、拓扑校验、后端同步)时用编辑器三包。两者可共存,但同一场景二选一。
下一步
- 核心概念 —— 引擎 / 命令 / 撤销重做 / 类型校验 / 吸附 / 拓扑 / 后端同步
- OpenLayers 适配器 · MapLibre 适配器
- 编辑器 API 参考
在线示例:仓库
examples/editor/(OL)与examples/editor-libre/(MapLibre)(pnpm dev:examples→/editor/、/editor-libre/)。在线 Playground 的「要素编辑全功能」预设(OpenLayers / MapLibre 两轨)把上表的全部模式与命令做成可一键试用的工具条——含撤销/重做、复制粘贴、面差集 / 挖洞 / 填洞 / 开洞 / 消洞、多部件拆分、Mock 后端同步与冲突演示。
