bigmap-plugin 1.0.5 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +402 -12
- package/dist/bigmap-plugin.js +2445 -1690
- package/dist/bigmap-plugin.umd.cjs +14 -14
- package/dist/index.d.ts +382 -20
- package/dist/libs/bigemap/BigemapElevationContourLayer.js +613 -0
- package/package.json +8 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**基于 bigemap / bmgl 的地图插件**,开箱即用的 Vue3 地图组件。
|
|
4
4
|
|
|
5
|
-
高性能点位渲染(10 万级)· 交互式绘制 · 实体绘制 · 轨迹回放 · 遮罩反选 · 天气特效 · 3D 自动光源 · 生产底图切换
|
|
5
|
+
高性能点位渲染(10 万级)· 交互式绘制 · 实体绘制 · 轨迹回放 · 遮罩反选 · KML 数据加载 · 天气特效 · 3D 自动光源 · 生产底图切换
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
- [4.12 3D 自动光源](#412-3d-自动光源)
|
|
37
37
|
- [4.13 主题切换](#413-主题切换)
|
|
38
38
|
- [4.14 视图与地图](#414-视图与地图)
|
|
39
|
+
- [4.15 KML 数据加载](#415-kml-数据加载)
|
|
39
40
|
- [5. Composable 独立使用](#5-composable-独立使用)
|
|
40
41
|
- [6. 常见问题 FAQ](#6-常见问题-faq)
|
|
41
42
|
- [License](#license)
|
|
@@ -176,11 +177,11 @@ api.startDrawing('rectangle') // 开始交互式绘制
|
|
|
176
177
|
| `searchDebounceTime` | `number` | `300` | 否 | 搜索输入防抖延迟(ms) |
|
|
177
178
|
| `wmtsUrlProvider` | `() => Promise<string>` | `undefined` | 否 | 生产底图 WMTS URL 提供器:返回带令牌的 WMTS 请求地址,**优先级高于 `geoserver`**,见 [3.2.1](#321-生产底图切换wmtsurlprovider--geoserver) |
|
|
178
179
|
| `geoserver` | `GeoServerSourceConfig` | `undefined` | 否 | 生产地图(GeoServer)源配置:提供 `baseUrl` / `layer` / `token`,配置后启用物探/生产底图切换,见 [3.2.1](#321-生产底图切换wmtsurlprovider--geoserver) |
|
|
179
|
-
| `contourConfig` | `Partial<ContourConfig>` |
|
|
180
|
+
| `contourConfig` | `Partial<ContourConfig>` | 内置默认(等高距 150m / 线宽 2px / 内置色带) | 否 | 彩色等高线显示配置(仅 3D),见 [4.8](#48-等高线显示) |
|
|
180
181
|
| `lightingConfig` | `boolean` | `false` | 否 | 是否开启 3D 自动光源(按系统时间) |
|
|
181
182
|
|
|
182
|
-
> **建议**:除 `theme` / `popupConfig` 外,其余配置统一放入 `config` 集中管理,代码更整洁。
|
|
183
|
-
|
|
183
|
+
> **建议**:除 `theme` / `popupConfig` 外,其余配置统一放入 `config` 集中管理,代码更整洁。
|
|
184
|
+
|
|
184
185
|
> **底图图层(`baseLayers` 与 `mapId` 的分工)**:`mapId` 是引擎(Viewer)自带的基础影像,`baseLayers` 是初始化时叠加在其上的底图图层列表。两者都会随「影像 / 生产底图」切换按钮一起生效:切回影像底图时按 `baseLayers` 重新加载。若只配 `mapId`、未配 `baseLayers`,默认的卫星影像 + 街道地名图层会盖在基础影像之上。
|
|
185
186
|
|
|
186
187
|
### 3.2 config 统一配置对象
|
|
@@ -936,29 +937,103 @@ const layers = getAllLayers() // 获取全部图层
|
|
|
936
937
|
|
|
937
938
|
### 4.8 等高线显示
|
|
938
939
|
|
|
939
|
-
**功能简介**:通过替换地表材质,在 **3D 模式**
|
|
940
|
+
**功能简介**:通过替换地表材质,在 **3D 模式** 下叠加彩色等高线(黑色描边 + 彩色主线 + 高程色带),并可按需在当前视区叠加固定高程标签。2D 模式自动关闭。
|
|
941
|
+
|
|
942
|
+
等高线渲染由随包发布的 `BigemapElevationContourLayer` 完成,**仅在首次开启等高线时动态加载**,地图初始化不加载该脚本。
|
|
940
943
|
|
|
941
944
|
**支持的小功能**:
|
|
942
945
|
|
|
943
946
|
- [切换等高线 setContourVisible](#切换等高线-setcontourvisible)
|
|
947
|
+
- [加载高程标签 loadContourLabels](#加载高程标签-loadcontourlabels)
|
|
948
|
+
- [移除高程标签 clearContourLabels](#移除高程标签-clearcontourlabels)
|
|
949
|
+
- [高程图例 getContourLegend](#高程图例-getcontourlegend)
|
|
950
|
+
- [等高线状态 contourState](#等高线状态-contourstate)
|
|
944
951
|
- [等高线配置 contourConfig](#等高线配置-contourconfig)
|
|
945
952
|
|
|
946
953
|
#### 切换等高线 `setContourVisible`
|
|
947
954
|
|
|
948
955
|
```ts
|
|
949
|
-
api.setContourVisible(true)
|
|
950
|
-
api.setContourVisible(false)
|
|
956
|
+
await api.setContourVisible(true) // 开启彩色等高线(仅 3D 生效)
|
|
957
|
+
api.setContourVisible(false) // 关闭
|
|
958
|
+
```
|
|
959
|
+
|
|
960
|
+
首次开启时需先加载等高线库,因此返回 `Promise`;库加载失败时开关自动回退为关闭状态。
|
|
961
|
+
|
|
962
|
+
#### 加载高程标签 `loadContourLabels`
|
|
963
|
+
|
|
964
|
+
按需读取当前视区地形高程,在跨越的等高线上放置固定高程标签。地图移动 / 缩放不会自动重算,避免持续占用主线程;需先开启等高线。
|
|
965
|
+
|
|
966
|
+
```ts
|
|
967
|
+
const result = await api.loadContourLabels()
|
|
968
|
+
// { status, labelCount, error? }
|
|
969
|
+
```
|
|
970
|
+
|
|
971
|
+
| `status` | 含义 |
|
|
972
|
+
| --- | --- |
|
|
973
|
+
| `success` | 加载成功,`labelCount` 为标签数量 |
|
|
974
|
+
| `no-results` | 当前视区未找到可标注的等高线 |
|
|
975
|
+
| `terrain-loading` | 地形尚未加载完成,稍后重试 |
|
|
976
|
+
| `unsupported` | 当前 SDK 不支持高程标签集合 |
|
|
977
|
+
| `hidden` | 等高线未开启 |
|
|
978
|
+
| `busy` | 上一次加载尚未完成 |
|
|
979
|
+
| `error` | 加载异常,`error` 为原始错误对象 |
|
|
980
|
+
|
|
981
|
+
#### 移除高程标签 `clearContourLabels`
|
|
982
|
+
|
|
983
|
+
```ts
|
|
984
|
+
const result = api.clearContourLabels()
|
|
985
|
+
// { status: 'cleared' | 'empty' | 'busy' | 'destroyed', labelCount: 0 }
|
|
986
|
+
```
|
|
987
|
+
|
|
988
|
+
#### 高程图例 `getContourLegend`
|
|
989
|
+
|
|
990
|
+
返回绘制 HTML 图例所需的数据副本(未开启等高线时返回 `null`):
|
|
991
|
+
|
|
992
|
+
```ts
|
|
993
|
+
const legend = api.getContourLegend()
|
|
994
|
+
// { minHeight, maxHeight, legendColorStep, colorStops: [{ height, color }, ...] }
|
|
995
|
+
```
|
|
996
|
+
|
|
997
|
+
#### 等高线状态 `contourState`
|
|
998
|
+
|
|
999
|
+
```ts
|
|
1000
|
+
api.contourState.value
|
|
1001
|
+
// { enabled, labelsLoading, labelCount, contourSpacing, labelSpacing, contourWidth, outlineWidth }
|
|
951
1002
|
```
|
|
952
1003
|
|
|
953
1004
|
#### 等高线配置 `contourConfig`
|
|
954
1005
|
|
|
955
1006
|
| 字段 | 类型 | 默认值 | 说明 |
|
|
956
1007
|
| --- | --- | --- | --- |
|
|
957
|
-
| `
|
|
958
|
-
| `
|
|
1008
|
+
| `contourSpacing` | `number` | `150` | 等高距(m) |
|
|
1009
|
+
| `contourWidth` | `number` | `2` | 彩色主线宽度(px) |
|
|
1010
|
+
| `outlineWidth` | `number` | `2` | 黑色描边宽度(px) |
|
|
1011
|
+
| `labelEvery` | `number` | `5` | 每隔多少条等高线显示一个高程标签 |
|
|
1012
|
+
| `maxLabels` | `number` | `28` | 当前视区最多显示的高程标签数量 |
|
|
1013
|
+
| `labelMinDistance` | `number` | `140` | 标签之间的最小屏幕间距(px) |
|
|
1014
|
+
| `labelOutlineWidth` | `number` | `3` | 标签文字描边宽度(px) |
|
|
1015
|
+
| `sampleStep` | `number` | `80` | 高程采样步长(px) |
|
|
1016
|
+
| `scanStep` | `number` | `120` | 视口扫描步长(px) |
|
|
1017
|
+
| `viewportMargin` | `number` | `48` | 视口边缘留白(px) |
|
|
1018
|
+
| `legendColorStep` | `number` | `500` | 图例色阶间隔(m) |
|
|
1019
|
+
| `minHeight` | `number` | 取色带首节点 | 色带最低高程(m) |
|
|
1020
|
+
| `maxHeight` | `number` | 取色带末节点 | 色带最高高程(m) |
|
|
1021
|
+
| `colorStops` | `ContourColorStop[]` | 内置 20 级色带 | 高程颜色节点 `{ height, color }`;配置后默认按首尾节点推导高程范围 |
|
|
959
1022
|
|
|
960
1023
|
```vue
|
|
961
|
-
<MapContainer :config="{
|
|
1024
|
+
<MapContainer :config="{
|
|
1025
|
+
contourConfig: {
|
|
1026
|
+
contourSpacing: 100,
|
|
1027
|
+
contourWidth: 2,
|
|
1028
|
+
outlineWidth: 2,
|
|
1029
|
+
labelEvery: 2,
|
|
1030
|
+
colorStops: [
|
|
1031
|
+
{ height: 0, color: '#0066FF' },
|
|
1032
|
+
{ height: 3000, color: '#FF8A00' },
|
|
1033
|
+
{ height: 6000, color: '#00F078' }
|
|
1034
|
+
]
|
|
1035
|
+
}
|
|
1036
|
+
}" />
|
|
962
1037
|
```
|
|
963
1038
|
|
|
964
1039
|
---
|
|
@@ -1255,6 +1330,319 @@ api.setMapNameVisible(false) // 隐藏
|
|
|
1255
1330
|
|
|
1256
1331
|
---
|
|
1257
1332
|
|
|
1333
|
+
### 4.15 KML 数据加载
|
|
1334
|
+
|
|
1335
|
+
**功能简介**:加载 KML 数据并渲染为地图要素,支持两种数据输入方式:远程地址(`loadKmlFromUrl`)与直接传入 KML 文本(`loadKmlFromText`)。自动解析 Placemark 的点 / 线 / 面(含 MultiGeometry 展开与内环「洞」)、共享样式(`Style` / `styleUrl` / `StyleMap`,含内联样式覆盖)与 `ExtendedData` 属性;2D / 3D 通用,模式切换自动重建。加载失败时给出中文提示,可通过状态直接展示,也可 `await` + `try/catch` 捕获。
|
|
1336
|
+
|
|
1337
|
+
**支持的小功能**:
|
|
1338
|
+
|
|
1339
|
+
- [地址加载 loadKmlFromUrl](#地址加载-loadkmlfromurl)
|
|
1340
|
+
- [文本加载 loadKmlFromText](#文本加载-loadkmlfromtext)
|
|
1341
|
+
- [KML XML 结构规范](#kml-xml-结构规范)
|
|
1342
|
+
- [生成 KML XML 并加载](#生成-kml-xml-并加载)
|
|
1343
|
+
- [切换显隐 setKmlVisible](#切换显隐-setkmlvisible)
|
|
1344
|
+
- [清除数据 clearKml](#清除数据-clearkml)
|
|
1345
|
+
- [加载状态 kmlState](#加载状态-kmlstate)
|
|
1346
|
+
|
|
1347
|
+
#### 地址加载 `loadKmlFromUrl`
|
|
1348
|
+
|
|
1349
|
+
```ts
|
|
1350
|
+
const result = await api.loadKmlFromUrl(url, config?)
|
|
1351
|
+
```
|
|
1352
|
+
|
|
1353
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
1354
|
+
| --- | --- | --- | --- |
|
|
1355
|
+
| `url` | `string` | 是 | KML 文件地址,支持绝对地址(`http(s)://...`)与相对地址(如 `/chengdu.kml`);仅支持 `http/https/blob/data` 协议 |
|
|
1356
|
+
| `config` | `KmlConfig` | 否 | 本次加载的配置,覆盖初始化时的默认配置 |
|
|
1357
|
+
|
|
1358
|
+
返回值 `KmlLoadResult`:`featureCount`(要素数)、`polygonCount` / `lineCount` / `pointCount`(各几何数量)、`features`(解析后的要素,含 `properties` 属性,可供弹窗等二次消费)等。
|
|
1359
|
+
|
|
1360
|
+
**示例**:
|
|
1361
|
+
|
|
1362
|
+
```ts
|
|
1363
|
+
try {
|
|
1364
|
+
const { featureCount } = await api.loadKmlFromUrl('/chengdu.kml')
|
|
1365
|
+
console.log('已加载要素数:', featureCount)
|
|
1366
|
+
} catch (error) {
|
|
1367
|
+
// 无效地址 / 网络失败 / HTTP 异常 / 解析失败 等均在此捕获
|
|
1368
|
+
console.warn((error as Error).message)
|
|
1369
|
+
}
|
|
1370
|
+
```
|
|
1371
|
+
|
|
1372
|
+
#### 文本加载 `loadKmlFromText`
|
|
1373
|
+
|
|
1374
|
+
```ts
|
|
1375
|
+
const result = await api.loadKmlFromText(text, config?)
|
|
1376
|
+
```
|
|
1377
|
+
|
|
1378
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
1379
|
+
| --- | --- | --- | --- |
|
|
1380
|
+
| `text` | `string` | 是 | KML 格式的 XML 文本内容,不能为空 |
|
|
1381
|
+
| `config` | `KmlConfig` | 否 | 本次加载的配置,覆盖初始化时的默认配置 |
|
|
1382
|
+
|
|
1383
|
+
**示例**:
|
|
1384
|
+
|
|
1385
|
+
```ts
|
|
1386
|
+
const response = await fetch('/chengdu.kml')
|
|
1387
|
+
const text = await response.text()
|
|
1388
|
+
const { featureCount } = await api.loadKmlFromText(text, { autoFlyTo: false })
|
|
1389
|
+
```
|
|
1390
|
+
|
|
1391
|
+
**`config`(`KmlConfig`)参数表**:
|
|
1392
|
+
|
|
1393
|
+
| 字段 | 类型 | 默认值 | 说明 |
|
|
1394
|
+
| --- | --- | --- | --- |
|
|
1395
|
+
| `fillColor` | `string` | `'#3d8bff'` | 面默认填充色(KML 未声明 `PolyStyle` 时使用) |
|
|
1396
|
+
| `fillAlpha` | `number` | `0.35` | 面默认填充透明度(0 ~ 1) |
|
|
1397
|
+
| `strokeColor` | `string` | `'#ffffff'` | 线 / 面轮廓默认颜色 |
|
|
1398
|
+
| `strokeAlpha` | `number` | `1` | 线 / 面轮廓默认透明度(0 ~ 1) |
|
|
1399
|
+
| `strokeWidth` | `number` | `2` | 线 / 面轮廓默认线宽(px) |
|
|
1400
|
+
| `pointColor` | `string` | `'#ff3b30'` | 点默认颜色 |
|
|
1401
|
+
| `pointPixelSize` | `number` | `8` | 点默认像素大小 |
|
|
1402
|
+
| `showLabel` | `boolean` | `true` | 是否显示要素名称标签(每个要素在代表点生成 1 个标签,随要素显隐) |
|
|
1403
|
+
| `labelColor` | `string` | `'#ffffff'` | 标签文字颜色 |
|
|
1404
|
+
| `labelFontSize` | `number` | `13` | 标签字号(px) |
|
|
1405
|
+
| `labelOutlineColor` | `string` | `'#000000'` | 标签文字描边颜色 |
|
|
1406
|
+
| `fillPalette` | `string[]` | `[]` | 按要素顺序轮换取色的调色板;非空时覆盖 KML 自身颜色(用于区分相邻区域),为空则不覆盖 |
|
|
1407
|
+
| `useKmlStyle` | `boolean` | `true` | 是否采用 KML 内联样式;`false` 时统一使用上述默认配色 |
|
|
1408
|
+
| `showFill` | `boolean` | `true` | 是否填充面(与 KML `PolyStyle.fill` 为「与」关系,两者同时为真才填充) |
|
|
1409
|
+
| `showOutline` | `boolean` | `true` | 是否绘制面外轮廓(与 KML `PolyStyle.outline` 为「与」关系) |
|
|
1410
|
+
| `extractProperties` | `boolean` | `true` | 是否解析 `ExtendedData` 到要素属性 |
|
|
1411
|
+
| `autoFlyTo` | `boolean` | `true` | 加载成功后是否自动飞行定位到数据范围 |
|
|
1412
|
+
| `timeout` | `number` | `15000` | 远程加载超时(ms),仅地址加载有效 |
|
|
1413
|
+
|
|
1414
|
+
#### KML XML 结构规范
|
|
1415
|
+
|
|
1416
|
+
插件内置解析器按标签名(`localName`)匹配,不区分命名空间前缀(`<kml>` 与 `<kml:kml>` 均可),因此只需保证标签名与层级正确。支持的标签子集如下:
|
|
1417
|
+
|
|
1418
|
+
| 标签 | 出现位置 | 必需 | 说明 |
|
|
1419
|
+
| --- | --- | --- | --- |
|
|
1420
|
+
| `<kml>` | 根节点 | 是 | 根节点名必须是 `kml`,否则报 `PARSE_FAILED` |
|
|
1421
|
+
| `<Document>` / `<Folder>` | 可任意层级嵌套 | 否 | 用于分组,仅影响遍历;Placemark 会被递归收集,与嵌套深度无关 |
|
|
1422
|
+
| `<Placemark>` | Document / Folder 内 | 是(至少一个) | 一个要素;文档内无任何可渲染几何时报 `NO_FEATURES` |
|
|
1423
|
+
| `<name>` | Placemark 内 | 否 | 要素名,缺省时回退为 Placemark 的 `id`;同时作为地图上名称标签的文字 |
|
|
1424
|
+
| `<visibility>` | Placemark 内 | 否 | 值为 `0` 时该要素默认隐藏(整体显隐不会强制显示它) |
|
|
1425
|
+
| `<styleUrl>` | Placemark 内 | 否 | 引用样式 id,写法 `#styleId` |
|
|
1426
|
+
| `<Style id>` | Document 内(任意层级均可被收集) | 否 | 样式定义;写在 Placemark 内时作为内联样式,覆盖 `styleUrl` 引用的结果 |
|
|
1427
|
+
| `<LineStyle>` | Style 内 | 否 | 含 `<color>`(aabbggrr)与 `<width>`(px),作用于线与面轮廓 |
|
|
1428
|
+
| `<PolyStyle>` | Style 内 | 否 | 含 `<color>`、`<fill>`(`0`/`1`)、`<outline>`(`0`/`1`) |
|
|
1429
|
+
| `<IconStyle>` | Style 内 | 否 | 含 `<color>`、`<scale>`、`<Icon><href>` |
|
|
1430
|
+
| `<StyleMap id>` | Document 内 | 否 | 取 `normal` 分支的 `styleUrl`(可穿透引用,自动解引用到目标 Style) |
|
|
1431
|
+
| `<Point><coordinates>` | Placemark 内 | 否 | 单个坐标 |
|
|
1432
|
+
| `<LineString><coordinates>` | Placemark 内 | 否 | 至少 2 个坐标,不足则跳过该几何 |
|
|
1433
|
+
| `<Polygon>` | Placemark 内 | 否 | 外环 `<outerBoundaryIs><LinearRing><coordinates>` 至少 3 个坐标;洞用 `<innerBoundaryIs>` 表达,可多个 |
|
|
1434
|
+
| `<MultiGeometry>` | Placemark 内 | 否 | 其内部几何会被展开为多个几何,一个 Placemark 可产出多个面 |
|
|
1435
|
+
| `<ExtendedData>` | Placemark 内 | 否 | 支持 `<SchemaData><SimpleData name="...">值</SimpleData>` 与 `<Data name="..."><value>值</value></Data>` 两种写法,结果进入 `features[].properties` |
|
|
1436
|
+
| `<Schema>` | Document 内 | 否 | 仅作声明用,解析属性时不依赖它,可省略 |
|
|
1437
|
+
|
|
1438
|
+
**四条必须遵守的编码规则**:
|
|
1439
|
+
|
|
1440
|
+
1. **颜色是 `aabbggrr`,不是 `#rrggbb`**:8 位十六进制,字节序为「alpha、蓝、绿、红」,与 CSS 的 `#rrggbb` 正好相反,且 alpha 在前。
|
|
1441
|
+
- 例:CSS `#4d90fe`(蓝)配 50% 透明度 → `50fe904d`(`50` = alpha,`fe` = 蓝,`90` = 绿,`4d` = 红)
|
|
1442
|
+
- 换算:`alpha` 字节 = `round(透明度 × 255)` 的两位十六进制,其后依次拼 `bb`、`gg`、`rr`
|
|
1443
|
+
- 也兼容 6 位 `rrggbb`(按不透明处理),非法值回退为默认配色
|
|
1444
|
+
2. **坐标格式为 `经度,纬度[,高程]`**:多个坐标元组之间用空白(空格或换行)分隔;高程省略时按 `0` 处理,非数字的元组会被跳过。
|
|
1445
|
+
3. **环必须首尾闭合**:`LinearRing` 的最后一个坐标应重复第一个坐标;洞(`innerBoundaryIs`)同样需要闭合。
|
|
1446
|
+
4. **无效几何只跳过自身**:不足 3 点的面、不足 2 点的线会被丢弃,不影响同文档其他要素;若整个文档一个可渲染几何都没有,则报 `NO_FEATURES`。
|
|
1447
|
+
|
|
1448
|
+
**配色两种做法,二选一**:
|
|
1449
|
+
|
|
1450
|
+
- 在 KML 里写 `<Style>` + `<styleUrl>`,由数据自身决定每个要素的颜色(适合颜色有业务含义的场景,见下方生成示例);
|
|
1451
|
+
- 不在 KML 里写样式,改用配置项 `fillPalette` 让插件按要素顺序轮换取色(适合只想区分相邻区域的场景,无需生成样式)。
|
|
1452
|
+
|
|
1453
|
+
#### 生成 KML XML 并加载
|
|
1454
|
+
|
|
1455
|
+
下面的 `buildKml` 是一段自包含的生成函数(不依赖本库任何导出),把业务数据拼成 KML 文本,再交给 `loadKmlFromText` 加载。
|
|
1456
|
+
|
|
1457
|
+
```ts
|
|
1458
|
+
/** #rrggbb + 透明度(0~1) → KML 的 aabbggrr */
|
|
1459
|
+
function toKmlColor(hex: string, alpha: number): string {
|
|
1460
|
+
const r = parseInt(hex.slice(1, 3), 16)
|
|
1461
|
+
const g = parseInt(hex.slice(3, 5), 16)
|
|
1462
|
+
const b = parseInt(hex.slice(5, 7), 16)
|
|
1463
|
+
const h2 = (v: number): string => v.toString(16).padStart(2, '0')
|
|
1464
|
+
return `${h2(Math.round(alpha * 255))}${h2(b)}${h2(g)}${h2(r)}`
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
/** XML 文本转义(名称等业务字段可能含 & < > " ') */
|
|
1468
|
+
function escapeXml(value: string): string {
|
|
1469
|
+
return value
|
|
1470
|
+
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
|
1471
|
+
.replace(/"/g, '"').replace(/'/g, ''')
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
interface Region {
|
|
1475
|
+
/** 区域名称:会作为地图上的名称标签文字 */
|
|
1476
|
+
name: string
|
|
1477
|
+
/** 区域颜色 #rrggbb */
|
|
1478
|
+
color: string
|
|
1479
|
+
/** 外环坐标(可不闭合,生成时会自动补首点) */
|
|
1480
|
+
ring: Array<{ lng: number; lat: number }>
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
function buildKml(regions: Region[]): string {
|
|
1484
|
+
const lines: string[] = [
|
|
1485
|
+
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
1486
|
+
'<kml xmlns="http://www.opengis.net/kml/2.2">',
|
|
1487
|
+
' <Document id="root_doc">'
|
|
1488
|
+
]
|
|
1489
|
+
|
|
1490
|
+
// 1) 每个区域一条 Style,Placemark 通过 styleUrl 引用
|
|
1491
|
+
regions.forEach((region, i) => {
|
|
1492
|
+
lines.push(
|
|
1493
|
+
` <Style id="style_${i}">`,
|
|
1494
|
+
` <LineStyle><color>${toKmlColor(region.color, 1)}</color><width>2</width></LineStyle>`,
|
|
1495
|
+
` <PolyStyle><color>${toKmlColor(region.color, 0.35)}</color></PolyStyle>`,
|
|
1496
|
+
' </Style>'
|
|
1497
|
+
)
|
|
1498
|
+
})
|
|
1499
|
+
|
|
1500
|
+
// 2) 每个区域一个 Placemark:名称 + 属性 + 面
|
|
1501
|
+
regions.forEach((region, i) => {
|
|
1502
|
+
const name = escapeXml(region.name)
|
|
1503
|
+
const ring = [...region.ring]
|
|
1504
|
+
const first = ring[0]
|
|
1505
|
+
const last = ring[ring.length - 1]
|
|
1506
|
+
// 规则 3:环首尾闭合,末点补首点
|
|
1507
|
+
if (first && last && (first.lng !== last.lng || first.lat !== last.lat)) {
|
|
1508
|
+
ring.push(first)
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
lines.push(
|
|
1512
|
+
` <Placemark id="region_${i + 1}">`,
|
|
1513
|
+
` <name>${name}</name>`,
|
|
1514
|
+
` <styleUrl>#style_${i}</styleUrl>`,
|
|
1515
|
+
' <ExtendedData>',
|
|
1516
|
+
' <SchemaData schemaUrl="#region.schema">',
|
|
1517
|
+
` <SimpleData name="BM_Name">${name}</SimpleData>`,
|
|
1518
|
+
` <SimpleData name="Code">R${String(i + 1).padStart(3, '0')}</SimpleData>`,
|
|
1519
|
+
' </SchemaData>',
|
|
1520
|
+
' </ExtendedData>',
|
|
1521
|
+
' <Polygon>',
|
|
1522
|
+
' <outerBoundaryIs><LinearRing><coordinates>',
|
|
1523
|
+
...ring.map((p) => ` ${p.lng},${p.lat},0`),
|
|
1524
|
+
' </coordinates></LinearRing></outerBoundaryIs>',
|
|
1525
|
+
' </Polygon>',
|
|
1526
|
+
' </Placemark>'
|
|
1527
|
+
)
|
|
1528
|
+
})
|
|
1529
|
+
|
|
1530
|
+
lines.push(' </Document>', '</kml>')
|
|
1531
|
+
return lines.join('\n')
|
|
1532
|
+
}
|
|
1533
|
+
```
|
|
1534
|
+
|
|
1535
|
+
**用法一:生成后直接加载(推荐,不落地文件、无网络请求)**
|
|
1536
|
+
|
|
1537
|
+
```ts
|
|
1538
|
+
const kmlText = buildKml([
|
|
1539
|
+
{
|
|
1540
|
+
name: '一号作业区',
|
|
1541
|
+
color: '#3d8bff',
|
|
1542
|
+
ring: [
|
|
1543
|
+
{ lng: 104.05, lat: 30.65 },
|
|
1544
|
+
{ lng: 104.12, lat: 30.65 },
|
|
1545
|
+
{ lng: 104.12, lat: 30.72 }
|
|
1546
|
+
]
|
|
1547
|
+
},
|
|
1548
|
+
{
|
|
1549
|
+
name: '二号作业区',
|
|
1550
|
+
color: '#ff9f0a',
|
|
1551
|
+
ring: [
|
|
1552
|
+
{ lng: 104.14, lat: 30.65 },
|
|
1553
|
+
{ lng: 104.21, lat: 30.65 },
|
|
1554
|
+
{ lng: 104.21, lat: 30.72 }
|
|
1555
|
+
]
|
|
1556
|
+
}
|
|
1557
|
+
])
|
|
1558
|
+
|
|
1559
|
+
const { features } = await api.loadKmlFromText(kmlText)
|
|
1560
|
+
features[0].name // '一号作业区'(即 <name>,也是地图上的标签文字)
|
|
1561
|
+
features[0].properties // { BM_Name: '一号作业区', Code: 'R001' }(来自 <ExtendedData>)
|
|
1562
|
+
```
|
|
1563
|
+
|
|
1564
|
+
**用法二:生成为 Blob URL 后按地址加载**
|
|
1565
|
+
|
|
1566
|
+
`loadKmlFromUrl` 支持 `blob:` 协议,因此无需部署静态文件也能走地址加载链路:
|
|
1567
|
+
|
|
1568
|
+
```ts
|
|
1569
|
+
const blob = new Blob([kmlText], { type: 'application/vnd.google-earth.kml+xml' })
|
|
1570
|
+
const objectUrl = URL.createObjectURL(blob)
|
|
1571
|
+
try {
|
|
1572
|
+
await api.loadKmlFromUrl(objectUrl)
|
|
1573
|
+
} finally {
|
|
1574
|
+
URL.revokeObjectURL(objectUrl)
|
|
1575
|
+
}
|
|
1576
|
+
```
|
|
1577
|
+
|
|
1578
|
+
**用法三:落地为 `.kml` 文件后由静态服务提供**
|
|
1579
|
+
|
|
1580
|
+
把 `kmlText` 存成文件(如 `public/regions.kml`),再 `api.loadKmlFromUrl('/regions.kml')`。适合数据量较大、需被多次复用或由后端直接下发的场景。
|
|
1581
|
+
|
|
1582
|
+
**关于名称标签**:`<name>` 的内容会渲染为地图上的名称标签,落点取面的包围盒中心(`MultiGeometry` 取面积最大的那个面;线取中点、点取自身坐标),文字默认白字黑描边。`showLabel` 默认为 `true`,不需要标签时加载传 `{ showLabel: false }` 即可;字号与颜色可经 `labelFontSize` / `labelColor` / `labelOutlineColor` 调整。
|
|
1583
|
+
|
|
1584
|
+
#### 切换显隐 `setKmlVisible`
|
|
1585
|
+
|
|
1586
|
+
```ts
|
|
1587
|
+
api.setKmlVisible(false) // 隐藏全部 KML 要素(保留数据)
|
|
1588
|
+
api.setKmlVisible(true) // 重新显示
|
|
1589
|
+
```
|
|
1590
|
+
|
|
1591
|
+
整体显隐与 KML 要素自身 `visibility` 叠加生效:KML 中 `visibility=0` 的要素不会被整体显隐强制显示。
|
|
1592
|
+
|
|
1593
|
+
#### 清除数据 `clearKml`
|
|
1594
|
+
|
|
1595
|
+
```ts
|
|
1596
|
+
api.clearKml() // 移除实体、清空数据并复位状态
|
|
1597
|
+
```
|
|
1598
|
+
|
|
1599
|
+
#### 加载状态 `kmlState`
|
|
1600
|
+
|
|
1601
|
+
响应式状态 `api.kmlState`,字段如下:
|
|
1602
|
+
|
|
1603
|
+
| 字段 | 类型 | 说明 |
|
|
1604
|
+
| --- | --- | --- |
|
|
1605
|
+
| `status` | `'idle' \| 'loading' \| 'success' \| 'error'` | 加载状态 |
|
|
1606
|
+
| `source` | `'url' \| 'text' \| null` | 数据来源 |
|
|
1607
|
+
| `url` | `string` | 数据来源地址(`source` 为 `url` 时有效) |
|
|
1608
|
+
| `featureCount` | `number` | 要素(Placemark)数量 |
|
|
1609
|
+
| `polygonCount` | `number` | 面(Polygon)数量 |
|
|
1610
|
+
| `lineCount` | `number` | 线(LineString)数量 |
|
|
1611
|
+
| `pointCount` | `number` | 点(Point)数量 |
|
|
1612
|
+
| `visible` | `boolean` | 是否显示中 |
|
|
1613
|
+
| `error` | `string \| null` | 错误提示(`status` 为 `error` 时有效) |
|
|
1614
|
+
|
|
1615
|
+
**错误提示说明**:加载失败时统一抛出 `KmlError`(含 `code` 与中文 `message`),并将提示写入 `kmlState.error`,两种方式可任选:
|
|
1616
|
+
|
|
1617
|
+
```ts
|
|
1618
|
+
// 方式一:直接绑定状态渲染提示(无需 try/catch)
|
|
1619
|
+
api.loadKmlFromUrl(url).catch(() => {})
|
|
1620
|
+
|
|
1621
|
+
// 方式二:捕获异常按错误码分支处理
|
|
1622
|
+
import { KmlError, KmlErrorCode } from 'bigmap-plugin'
|
|
1623
|
+
try {
|
|
1624
|
+
await api.loadKmlFromText(text)
|
|
1625
|
+
} catch (error) {
|
|
1626
|
+
if (error instanceof KmlError && error.code === KmlErrorCode.PARSE_FAILED) {
|
|
1627
|
+
console.warn('KML 格式有误:', error.message)
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1630
|
+
```
|
|
1631
|
+
|
|
1632
|
+
| 错误码 `KmlErrorCode` | 触发场景 |
|
|
1633
|
+
| --- | --- |
|
|
1634
|
+
| `INVALID_URL` | 地址为空、非字符串或不支持的协议 |
|
|
1635
|
+
| `INVALID_TEXT` | 文本为空或非字符串 |
|
|
1636
|
+
| `PARSE_FAILED` | XML 格式错误或根节点不是 `<kml>` |
|
|
1637
|
+
| `NO_FEATURES` | 解析成功但无任何可渲染几何(如空文档) |
|
|
1638
|
+
| `NETWORK_FAILED` | 请求发起失败或读取响应内容失败 |
|
|
1639
|
+
| `HTTP_ERROR` | 服务器返回非 2xx 状态码 |
|
|
1640
|
+
| `TIMEOUT` | 远程加载超时 |
|
|
1641
|
+
| `MAP_NOT_READY` | 地图尚未初始化完成 |
|
|
1642
|
+
| `LOAD_FAILED` | 其他异常的统一兜底 |
|
|
1643
|
+
|
|
1644
|
+
---
|
|
1645
|
+
|
|
1258
1646
|
## 5. Composable 独立使用
|
|
1259
1647
|
|
|
1260
1648
|
除通过 `MapContainer` 组件使用外,也可在自定义 `<script setup>` 中直接组合 `composable`,获得更细粒度的控制。所有 composable 均通过具名导出引入:
|
|
@@ -1271,6 +1659,7 @@ import {
|
|
|
1271
1659
|
useMapContour,
|
|
1272
1660
|
useMapTrajectory,
|
|
1273
1661
|
useMapMask,
|
|
1662
|
+
useMapKml,
|
|
1274
1663
|
useMapWeather,
|
|
1275
1664
|
useMapLighting,
|
|
1276
1665
|
} from 'bigmap-plugin'
|
|
@@ -1287,9 +1676,10 @@ import {
|
|
|
1287
1676
|
| `useMapPopup(map, event?, options?)` | 点位弹窗 | `showPointPopup` / `removePopup` / `isPopupVisible` / `getCurrentPopupData` |
|
|
1288
1677
|
| `useMapCircleWave(map)` | 圆形波动 | `addWave` / `removeWave` |
|
|
1289
1678
|
| `useMapLayers(map)` | 图层管理 | `addImageryLayer` / `addWmtsLayer` / `removeLayer` / `removeAllLayers` / `setLayerVisible` / `setLayerOpacity` |
|
|
1290
|
-
| `useMapContour(map, config?)` |
|
|
1679
|
+
| `useMapContour(map, config?, deps?)` | 彩色等高线 | `setContourVisible` / `loadLabels` / `clearLabels` / `getLegendData` / `reapply` / `remove` |
|
|
1291
1680
|
| `useMapTrajectory(map, config?, deps?)` | 轨迹回放 | `load` / `play` / `pause` / `stop` / `setSpeed` / `jumpTo` / `clear` / `reapply` / `destroy` |
|
|
1292
1681
|
| `useMapMask(map, config?)` | 遮罩反选 | `setMask` / `setVisible` / `clear` / `reapply` / `remove` / `destroy` |
|
|
1682
|
+
| `useMapKml(map, config?)` | KML 数据加载 | `loadFromUrl` / `loadFromText` / `getFeatures` / `setVisible` / `flyTo` / `remove` / `clear` / `reapply` / `destroy` |
|
|
1293
1683
|
| `useMapWeather(map, config?)` | 天气特效 | `setWeather` / `clear` / `destroy` |
|
|
1294
1684
|
| `useMapLighting(map, config?, options?)` | 3D 光源 | `setEnabled` / `setPeriod` / `apply` / `destroy` |
|
|
1295
1685
|
|
|
@@ -1361,7 +1751,7 @@ const load = async () => {
|
|
|
1361
1751
|
|
|
1362
1752
|
**Q5:等高线 / 3D 光源不生效?**
|
|
1363
1753
|
|
|
1364
|
-
两者**仅 3D 模式**有效,切到 2D 会自动关闭 /
|
|
1754
|
+
两者**仅 3D 模式**有效,切到 2D 会自动关闭 / 还原。等高线还需确认等高线库可访问:首次开启时会从 `libsUrl`(默认 `/libs`)加载 `libs/bigemap/BigemapElevationContourLayer.js`,若该资源不可达则开关会自动回退为关闭,控制台会输出加载失败日志。
|
|
1365
1755
|
|
|
1366
1756
|
**Q6:轨迹加载后不动?**
|
|
1367
1757
|
|