dji-wayline-map
v0.2.0
Published
解析大疆(DJI)航线 KMZ 文件并在高德地图(AMap)上绘制航线:KML 解析 + WGS84↔GCJ02 坐标转换 + 航点倒三角标记 + SVG 航段连线 + 自动适配视野。框架无关,传入 AMap 实例即可使用。
Maintainers
Readme
dji-wayline-map
解析大疆(DJI)航线 KMZ 文件,并在高德地图(AMap)上绘制航线:KML 解析 + WGS84↔GCJ02 坐标转换 + 航点倒三角标记 + SVG 航段连线 + 自动适配视野。
框架无关 —— 解析与坐标转换是纯函数;地图绘制接受一个高德地图实例即可工作,不绑定 React/Vue。高德 JSAPI 由调用方自行加载,本包不打包、不加载。
安装
npm install dji-wayline-map
# 或
pnpm add dji-wayline-map
fflate与fast-xml-parser会作为常规依赖安装。高德地图 JSAPI 需由调用方加载(见下文)。
快速开始
import {
parseWaylineToGcj02,
createWaylineDrawer,
} from "dji-wayline-map";
// 1) 加载高德 JSAPI(由调用方负责,得到 window.AMap)
// 参考 https://lbs.amap.com/api/javascript-api/guide/abc/prepare
const AMap = window.AMap;
const map = new AMap.Map(container, { zoom: 15, center: [120.05, 30.28] });
// 2) 创建绘制控制器(持有整条航线的标记/连线/事件状态)
const drawer = createWaylineDrawer(map, AMap, {
markerColor: "#00E5A8",
lineColor: "#00E5A8",
});
// 3) 下载航线 KMZ -> 解析为 GCJ02 路径 -> 绘制
const res = await fetch(kmzUrl);
const buf = await res.arrayBuffer();
const path = await parseWaylineToGcj02(buf, { maxPoints: 3000 });
drawer.draw(path);
// 切换航线时再次 draw() 即可,会自动清理上一条
// drawer.clear(); // 仅清除
// drawer.destroy(); // 销毁控制器(解绑事件、释放 ResizeObserver)API
解析
| 函数 | 说明 |
| --- | --- |
| parseKmzDocument(buf, options?): Promise<WaylineDocument> | 结构化解析 KMZ,返回航点元数据、选中文件和警告;支持资源限制、取消和严格模式。 |
| parseKmzMissions(buf, options?): Promise<WaylineMission[]> | 返回 KMZ 中全部任务,并关联 template.kml 与 waylines.wpml。 |
| parseKmlDocument(text, options?): WaylineDocument | 使用 XML 解析器读取 KML/WPML,保留 DJI 高度、速度、航向、云台俯仰和动作。 |
| parseKmlMissions(text, options?): WaylineDocument[] | 将多个 Folder 解析为独立任务。 |
| parseWaylineInWorker(buf, options?) | 在 Web Worker 中解析,支持进度、取消及 transferable ArrayBuffer;通过 workerUrl 或 workerFactory 注入 runtime。 |
| parseKmzArrayBuffer(buf): Promise<LngLat[]> | 解析 KMZ(zip)ArrayBuffer,遍历 .kml / .wpml 候选并返回点数最多的原始 WGS84 路径。 |
| parseKmlToPath(kmlText): LngLat[] | 解析 KML 文本。优先级:① Placemark <Point> 航点(≥2)→ ② 最长 <coordinates>(LineString)→ ③ 兜底 <gx:coord> 轨迹点。 |
| parseWaylinePath(buf): Promise<LngLat[]> | 等价于 parseKmzArrayBuffer,语义化别名。 |
| parseWaylineToGcj02(buf, opts?): Promise<LngLat[]> | 一步到位:解析 → 过滤非法点 → 抽稀(opts.maxPoints 默认 3000,必须 ≥2)→ WGS84→GCJ02,结果可直接喂给高德地图。 |
LngLat = [longitude, latitude]。
结构化解析示例:
import { parseKmzDocument, WaylineParseError } from "dji-wayline-map/parse";
try {
const document = await parseKmzDocument(buffer, {
maxArchiveBytes: 50 * 1024 * 1024,
maxEntries: 256,
maxTextBytes: 20 * 1024 * 1024,
maxCoordinates: 100_000,
signal: abortController.signal,
strict: true,
});
console.log(document.waypoints, document.warnings, document.sourceFile);
} catch (error) {
if (error instanceof WaylineParseError) console.error(error.code, error.message);
}Waypoint 包含 index、coordinate、altitude、speed、heading、gimbalPitch、强类型动作和动作组;文档同时保留飞机、载荷与任务配置。兼容 API 仍只返回坐标数组。KMZ 使用 64 KiB 分块解压,并在解压过程中执行累计字节限制。
坐标转换
| 函数 | 说明 |
| --- | --- |
| wgs84ToGcj02(lng, lat): { longitude, latitude } | WGS84 → GCJ02(火星坐标系)。境外坐标原样返回。 |
| gcj02ToWgs84(lng, lat, options?) | GCJ02 → WGS84,可配置迭代次数、精度和境内判断策略。 |
| wgs84PathToGcj02(path, options?) | 批量转换 WGS84 路径,不修改输入。 |
| gcj02PathToWgs84(path, options?) | 批量反算 GCJ02 路径,不修改输入。 |
路径工具
| 函数 | 说明 |
| --- | --- |
| samplePath(path, maxPoints): LngLat[] | 均匀抽稀并保留首尾点;maxPoints 必须是 ≥2 的整数。 |
| samplePathByDistance(path, maxPoints) | 按累计地表距离选择原始航点。 |
| simplifyPath(path, toleranceMeters) | RDP 米级容差简化,保留路线形状。 |
| simplifyPathToLimit(path, maxPoints) | 按几何重要性简化到点数上限。 |
| isValidLngLat(point): boolean | 经纬度合法性校验。 |
| dedupeConsecutive(points): LngLat[] | 去除连续重复点。 |
| calculatePathBounds(path) | 计算支持跨日期变更线的最小边界。 |
| geodesicDistance(a, b) | 计算两点地表距离。 |
| analyzeWayline(document) | 计算总里程、分段、爬升/下降、边界和预计时长。 |
| buildAltitudeProfile(document) | 生成累计距离/高度剖面数据。 |
高德地图绘制
createWaylineDrawer(map, AMap, options?): WaylineDrawer
创建一个有状态的航线绘制控制器。把原项目中散落在 React ref 里的绘制状态(标记数组、SVG 连线、拖拽/缩放事件、ResizeObserver)封装为框架无关对象。
参数
map—— 高德地图实例(AMap.Map)AMap—— AMap 命名空间(通常即window.AMap)options—— 可选样式与上限:
| 选项 | 默认值 | 说明 |
| --- | --- | --- |
| maxWorkingPoints | 2000 | 工作点上限,必须是 ≥2 的整数,超过先抽稀以减轻计算量 |
| maxMarkers | 120 | 地图上最多绘制的航点(倒三角)数量,必须是 ≥1 的整数 |
| triangleSide | 28 | 倒三角边长(px) |
| markerColor | '#00E5A8' | 航点倒三角填充色 |
| markerTextColor | '#ffffff' | 航点编号文字色 |
| selectedMarkerColor | '#FFB020' | 选中航点填充色 |
| lineColor | '#00E5A8' | SVG 航段连线颜色 |
| lineWidth | 4 | SVG 航段连线宽度(px) |
| zIndexMarker | 1000 | 航点 DOM 标记层级 |
| zIndexLine | 100 | SVG 连线层级 |
| fitViewPadding | [60,60,60,60] | 自动适配视野内边距 [top,right,bottom,left] 或单一值 |
| fitViewMaxZoom | 18 | 自动适配视野最大缩放级别 |
| pointZoom | 17 | 退化(单点)航线缩放级别 |
| svgClassName | 'dji-wayline-svg-lines' | SVG 连线元素 className,便于样式覆盖 |
| autoFitView | true | 绘制时自动适配视野 |
| visible | true | 初始可见性 |
| lineRenderer | 'auto' | 连线后端:auto、svg、canvas 或高德 amap Polyline |
| canvasThreshold | 5000 | auto 模式切换到 Canvas 的点数阈值 |
| draggableWaypoints | false | 启用原生 Marker 拖拽 |
| markerRenderer | - | 自定义 Marker 内容渲染器 |
| onWaypointClick | - | 航点点击回调,索引对应原始输入路径 |
| onWaypointMove | - | 航点拖拽完成回调,可与编辑器组合实现撤销/重做 |
| onError | - | 绘制错误回调,避免库直接输出 console |
返回 WaylineDrawer
| 方法 | 说明 |
| --- | --- |
| draw(path) | 绘制/覆盖一条航线(坐标需为 GCJ02)。空数组等价于 clear()。 |
| drawDocument(document, options?) | 绘制结构化文档并把航点元数据传给 Marker 回调;默认转换 WGS84。 |
| clear() | 清除标记与连线,保留控制器可再次 draw。 |
| refresh() | 强制重绘 SVG 连线。内部已监听拖拽/缩放/resize 自动刷新,一般无需手动调用。 |
| updateOptions(options) | 更新样式、上限或回调并重绘。 |
| setVisible(visible) | 显示或隐藏当前航线。 |
| setSelectedWaypoint(index) | 设置原始路径中的选中航点,传 null 取消。 |
| getDisplayedPath() | 返回当前保形简化后的连线路径副本。 |
| getBounds() | 返回当前原始有效路径边界。 |
| destroy() | 销毁:清除图形、解绑事件、释放 ResizeObserver。销毁后不可再用。 |
auto 后端优先使用高德官方 Polyline;不可用时,小航线使用单个 SVG <path>,大航线切换 Canvas。也可显式指定后端。SVG/Canvas 优先挂载到官方 pane,私有 DOM 类名仅作为兼容回退。
编辑与互操作
createWaylineEditor():插入、修改、移动、删除、重排、撤销/重做和变更订阅。toGeoJSON()/fromGeoJSON():GeoJSON LineString 往返转换。toKml()/toWpml():结构化序列化。createAdapterDrawer():面向 MapLibre、Leaflet、百度地图等 SDK 的通用适配器边界。
其他导出
waylineMarkerSvgContent(index, side?, fillColor?, textColor?)—— 生成航点倒三角 SVG 字符串。redrawWaylineSvgLines(map, AMap, displayPath, style)—— 低层级 SVG 重绘(一般无需直接使用)。
类型
export type LngLat = [number, number];
export interface WaylineDrawOptions { /* 见上表 */ }
export interface WaylineDrawer {
draw; clear; refresh; updateOptions; setVisible; setSelectedWaypoint;
getDisplayedPath; getBounds; destroy;
}
export interface AMapLike { Marker; LngLat; Bounds? }
export interface AMapMapLike { add; remove; getContainer; resize?; lngLatToContainer?; on; off?; setFitView?; setBounds?; setCenter; setZoom; }AMapLike / AMapMapLike 为结构化最小类型,任何满足形状的高德 JSAPI v2.0 实例均可通过类型检查。
子路径导出
按需导入可以让职责和依赖边界更清晰:
import { parseKmzDocument } from "dji-wayline-map/parse";
import { wgs84PathToGcj02 } from "dji-wayline-map/coord";
import { simplifyPath } from "dji-wayline-map/path";
import { createWaylineDrawer } from "dji-wayline-map/amap";
import { parseWaylineInWorker } from "dji-wayline-map/worker";
import { createWaylineEditor } from "dji-wayline-map/editor";
import { toGeoJSON } from "dji-wayline-map/interop";
import { createAdapterDrawer } from "dji-wayline-map/adapter";与原 DJI 飞控项目链路的对应关系
本包提炼自一条「选中航线 → 地图显示」链路:
| 原项目逻辑 | 本包对应 |
| --- | --- |
| 下载 KMZ → Worker/主线程解析 KML | parseKmzArrayBuffer / parseKmlToPath |
| 过滤 + 抽稀 3000 + WGS84→GCJ02 | parseWaylineToGcj02(buf, { maxPoints: 3000 }) |
| 坐标系转换 | wgs84ToGcj02 / gcj02ToWgs84 |
| drawWayline:标记点 + SVG 连线 + 自动适配 + 随拖拽刷新 | createWaylineDrawer(map, AMap).draw(path) |
原项目通过 window 自定义事件 wayline:draw 在页面与地图组件间通信,属应用层胶水代码,不在本包内。接入本包后,页面侧可直接调用 drawer.draw(path),或保留事件桥接在监听处调用。
许可证
MIT
