maplibre-label-util
v0.1.2
Published
Reusable MapLibre polygon and line annotation utilities based on Terra Draw.
Readme
maplibre-label-util
基于 MapLibre GL、Terra Draw 和 React 的可复用地图标注工具。
maplibre-label-util 可以帮助 React 应用以标准 GeoJSON Feature 的形式绘制、编辑、选中并同步地图标注。它支持多边形、线、点、吸附分支线绘制,以及 MultiLineString 共享交点编辑。
功能
- 绘制和编辑
Polygon标注。 - 绘制和编辑
LineString标注。 - 渲染和编辑
Point、MultiPoint、LineString、MultiLineString、PolygonGeoJSON 要素。 - 按住
Ctrl并点击已有线段,可以从吸附点开始绘制分支线。 - 分支线完成后输出为
MultiLineString。 - 编辑
MultiLineString的某条分支时,保持共享交点同步。 - 通过 MapLibre
beforeId控制图层插入顺序。 - 使用内置快捷键,或自定义多边形和线绘制快捷键。
- 通过
canEdit控制编辑权限,并通过回调接收被拒绝的编辑。
安装
安装包和 peer dependencies:
npm install maplibre-label-util maplibre-gl terra-draw terra-draw-maplibre-gl-adapter react使用 pnpm:
pnpm add maplibre-label-util maplibre-gl terra-draw terra-draw-maplibre-gl-adapter reactPeer Dependencies
宿主应用需要提供这些依赖:
| 依赖 | 支持版本 |
| -------------------------------- | -------- |
| maplibre-gl | >=5 |
| terra-draw | >=1.24 |
| terra-draw-maplibre-gl-adapter | >=1.3 |
| react | >=18 |
基本用法
import { useState } from "react";
import {
useMaplibreLabelDraw,
type LabelDrawState,
type LabelFeature,
type LabelId,
} from "maplibre-label-util";
export function AnnotationLayer({ map }: { map: maplibregl.Map | null }) {
const [labels, setLabels] = useState<LabelFeature[]>([]);
const [selectedId, setSelectedId] = useState<LabelId | null>(null);
const [drawState, setDrawState] = useState<LabelDrawState>("idle");
const draw = useMaplibreLabelDraw({
map,
enabled: true,
labels,
selectedId,
beforeId: "your-maplibre-layer-id",
shortcuts: {
polygonKey: "c",
lineKey: "v",
},
style: {
polygonColor: "#ef4444",
lineColor: "#ef4444",
pointColor: "#ef4444",
polygonVertexColor: "#dc2626",
lineVertexColor: "#991b1b",
snapPointColor: "#2563eb",
selectedPolygonColor: "#f97316",
selectedLineColor: "#f97316",
selectedPointColor: "#f97316",
selectedPolygonVertexColor: "#facc15",
selectedLineVertexColor: "#fb923c",
polygonFillOpacity: 0.3,
},
onCreate: (label) => setLabels((items) => [...items, label]),
onUpdate: (id, feature) =>
setLabels((items) =>
items.map((item) => (String(item.id) === String(id) ? feature : item)),
),
onSelect: (id) => setSelectedId(id),
onDrawStateChange: (state) => setDrawState(state),
});
return (
<div>
<button type="button" onClick={draw.startPolygon}>
Polygon
</button>
<button type="button" onClick={draw.startLine}>
Line
</button>
<button type="button" onClick={draw.cancel}>
Cancel
</button>
<span>{drawState}</span>
</div>
);
}labels 和回调参数都是带 id 的标准 GeoJSON Feature。支持的 geometry 类型包括 Point、MultiPoint、LineString、MultiLineString 和 Polygon。
Hook 配置
| 配置 | 类型 | 默认值 | 说明 |
| ------------------- | --------------------------------- | ----------- | ----------------------------------------------------------- |
| map | MaplibreMap \| null | 必填 | MapLibre map 实例。地图未初始化时可以传 null。 |
| labels | LabelFeature[] | 必填 | 需要渲染和编辑的标注数据。 |
| enabled | boolean | true | 为 false 时隐藏并禁用所有标注和吸附图层。 |
| beforeId | string | undefined | MapLibre 图层 id,用于控制绘制图层插入位置。 |
| selectedId | LabelId \| null | null | 应用状态中当前选中的标注 id。 |
| colors | Partial<LabelColors> | 红色默认值 | 兼容旧版本的颜色配置入口,新代码建议使用 style。 |
| style | LabelStyleOptions | 见下方 | 标注颜色和多边形透明度。 |
| layers | LabelLayerOptions | 内置 id | 自定义 Terra Draw 和吸附点的 source/layer id。 |
| shortcuts | boolean \| LabelShortcutOptions | true | 传 false 禁用全部快捷键,或传对象配置多边形和线绘制按键。 |
| branchLine | boolean | true | 是否启用 Ctrl 吸附分支线绘制。 |
| canEdit | (label) => boolean | true | 编辑权限判断。 |
| onCreate | (label) => void | undefined | 新标注完成时触发。 |
| onUpdate | (id, feature) => void | undefined | 已有标注 geometry 变化时触发。 |
| onSelect | (id, label) => void | undefined | 标注选中或取消选中时触发。 |
| onDrawStateChange | (state) => void | undefined | 绘制状态变化时触发。 |
| onEditRejected | (label) => void | undefined | canEdit 拒绝编辑时触发。 |
Style 配置
| 字段 | 说明 |
| ---------------------------- | -------------------------------- |
| polygonColor | 多边形描边和填充颜色。 |
| lineColor | 线颜色。 |
| pointColor | 点颜色。 |
| polygonVertexColor | 多边形未选中或绘制中的顶点颜色。 |
| lineVertexColor | 线未选中或绘制中的顶点颜色。 |
| snapPointColor | Ctrl 吸附点颜色。 |
| selectedPolygonColor | 选中多边形颜色。 |
| selectedLineColor | 选中线颜色。 |
| selectedPointColor | 选中点颜色。 |
| selectedPolygonVertexColor | 选中多边形顶点颜色。 |
| selectedLineVertexColor | 选中线顶点颜色。 |
| polygonFillOpacity | 多边形填充透明度。 |
快捷键
默认快捷键:
| 按键 | 动作 |
| -------- | ---------------------- |
| C | 开始或完成多边形绘制。 |
| V | 开始或完成线绘制。 |
| Enter | 完成当前绘制。 |
| Esc | 取消当前绘制。 |
| Ctrl+Z | 绘制中撤销最近一个点。 |
polygonKey 和 lineKey 不能与内部保留键 Enter、Escape、Control、Ctrl、Z 冲突,也不能彼此冲突。无效配置会被忽略并回退到默认按键。
分支线绘制
当 branchLine 启用时:
- 绘制前按住
Ctrl。 - 将鼠标移动到已有
LineString或MultiLineString线段附近。 - 点击吸附点。
- 绘制新的分支线。
- 使用
Enter、C或V完成绘制。
目标线会被更新为 MultiLineString。如果目标本身已经是 MultiLineString,新分支会追加进去,并保留共享交点关系。
绘制状态
onDrawStateChange 和返回值中的 drawState ref 支持这些状态:
| 状态 | 含义 |
| ----------------- | -------------------- |
| idle | 没有正在进行的绘制。 |
| polygon | 正在绘制多边形。 |
| lineString | 正在绘制线。 |
| multiLineString | 正在绘制分支线。 |
返回值
useMaplibreLabelDraw 返回:
| 字段 | 说明 |
| ---------------- | ------------------------------------------------------ |
| drawRef | 指向底层 TerraDraw 实例的 mutable ref。 |
| mode | 当前绘制模式的 mutable ref。 |
| drawState | 当前绘制状态的 mutable ref。 |
| startPolygon | 开始绘制多边形;如果已经在绘制多边形,则完成当前绘制。 |
| startLine | 开始绘制线;如果已经在绘制线,则完成当前绘制。 |
| cancel | 取消当前绘制并清理临时要素。 |
| selectLabel | 根据业务标注 id 选中标注。 |
| clearSelection | 清除 Terra Draw 当前选中要素。 |
| deleteFeature | 从地图中移除指定标注 id 对应的绘制要素。 |
| getSnapshot | 返回当前 Terra Draw snapshot。 |
TypeScript
包内置 TypeScript 类型声明。可以通过 useMaplibreLabelDraw 的泛型约束自定义 properties:
type RoadLabelProperties = {
name: string;
kind: "primary" | "secondary";
};
const draw = useMaplibreLabelDraw<RoadLabelProperties>({
map,
labels,
onUpdate: (id, feature) => {
feature.properties.name;
},
});