huweili-cesium 1.2.84 → 1.2.86

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 CHANGED
@@ -1,315 +1,315 @@
1
- # huweili-cesium
2
-
3
- 基于 Cesium 的地图工具库。所有 **JS 模块** 位于包内 `js/` 目录(含 `toolbar`、`stores`、`utils`、`config`、`api` 子目录);根目录保留 `index.js`(npm 主入口)与 `index.vue`(地图组件)。
4
-
5
- ## 安装
6
-
7
- ```bash
8
- npm install huweili-cesium
9
- ```
10
-
11
- ### 对等依赖(需在项目中已安装)
12
-
13
- - `cesium` 1.136.0
14
- - `vue` ^3.3
15
- - `pinia` ^2 或 ^3
16
- - `mitt` 3
17
- - `qrcode` 1.5
18
-
19
- ## 使用前准备
20
-
21
- 1. 在 HTML 中加载与宿主项目一致的 `constants.js`(定义 `window.DroneStatus`、`window.MapInstanceIds` 等),或自行赋值这些全局变量。
22
- 2. 在 Vue 应用中 `app.use(pinia)`,地图组件初始化后调用各 `*Config()` 工厂函数。
23
-
24
- ## 引入示例
25
-
26
- ### JS 模块
27
-
28
- ```js
29
- // 主入口同时支持:默认导出组件 + 命名导出 JS 模块
30
- import CesiumMap, { basicConfig, setPoint, movePointConfig } from 'huweili-cesium'
31
-
32
- // 仅 JS 模块(不含 Vue 组件)可用子路径
33
- import { basicConfig } from 'huweili-cesium/js'
34
-
35
- // 或按文件引入
36
- import { basicConfig } from 'huweili-cesium/basis'
37
- import { hemisphereConfig } from 'huweili-cesium/hemisphere'
38
- import { createCustomToolbarButtons } from 'huweili-cesium/customToolbarButtons'
39
- ```
40
-
41
- ### Vue 地图组件(开箱即用)
42
-
43
- ```vue
44
- <template>
45
- <div class="map-page">
46
- <CesiumMap map-id="default" @onload="onMapLoad" />
47
- </div>
48
- </template>
49
-
50
- <script setup>
51
- // 推荐:包主入口默认导出组件
52
- import CesiumMap from 'huweili-cesium'
53
- // 等价写法:
54
- // import CesiumMap from 'huweili-cesium/index.vue'
55
- // import CesiumMap from 'huweili-cesium/CesiumMap'
56
-
57
- function onMapLoad({ map, center }) {
58
- console.log('地图已加载', map, center)
59
- }
60
- </script>
61
-
62
- <style scoped>
63
- .map-page {
64
- width: 100%;
65
- height: 100vh;
66
- }
67
- </style>
68
- ```
69
-
70
- **Vite 宿主项目**需在 `vite.config` 中允许编译该依赖(否则 `.vue` 可能无法处理):
71
-
72
- ```js
73
- export default defineConfig({
74
- optimizeDeps: {
75
- include: ['huweili-cesium'],
76
- },
77
- })
78
- ```
79
-
80
- 组件 props:
81
-
82
- | prop | 类型 | 默认 | 说明 |
83
- |------|------|------|------|
84
- | `mapId` | `string` | `'default'` | 多地图实例 ID,与 `mapStore` 对应 |
85
- | `options` | `object` | — | 覆盖/合并 `MapConfig` 的配置 |
86
-
87
- 事件:`@onload`,参数 `{ map, center, mapId, toolbar }`(`map` 为 Cesium `Viewer` 实例;`toolbar` 可在加载后动态增删按钮)。
88
-
89
- ### 为何不用 Cesium 内置 2D 模式
90
-
91
- Viewer 固定为 `SCENE3D`,业务上的「2D」是 **正交相机 + 俯视**(`basis.js` / `cameraInteraction.js`),不切换 `SCENE2D` / `COLUMBUS_VIEW`。简要优点:
92
-
93
- - **2D/3D 切换更顺**:无场景变形(morph),透视与正交互换,缩放与锚点更易对齐(含工具栏切换、RTK 跟飞)。
94
- - **渲染一致**:无人机、轨迹、围栏等与 3D 同一套规则,少踩 2D 投影下的显示差异。
95
- - **交互可控**:2D 可锁定俯视、自定义滚轮缩放(正交宽度),避免与内置 2D 控制器行为不一致。
96
- - **语义清晰**:`mapStore` 的 `2D`/`3D` 表示业务视角,不与 Cesium `SceneMode` 枚举混用。
97
-
98
- 配置里 `scene.sceneMode: '2D'` 表示初始化俯视正交,而非启用 Cesium 平面地图模式。
99
-
100
- ### 各项目自定义工具栏
101
-
102
- **方式 1:组件 props(推荐)**
103
-
104
- ```vue
105
- <CesiumMap
106
- map-id="default"
107
- :show-default-toolbar="true"
108
- :extra-toolbar-buttons="myExtraButtons"
109
- />
110
- ```
111
-
112
- ```js
113
- import { useEventBus } from 'huweili-cesium/utils/useEventBus'
114
-
115
- const { emit } = useEventBus()
116
-
117
- const myExtraButtons = [
118
- {
119
- title: '导出',
120
- text: '导',
121
- onClick: () => emit('exportMap', {}),
122
- },
123
- ]
124
- ```
125
-
126
- 完全不用内置默认按钮、自己定义一整组:
127
-
128
- ```vue
129
- <CesiumMap :toolbar-buttons="myToolbarButtons" />
130
- ```
131
-
132
- 内置默认按钮里的图标路径使用宿主项目的 `import.meta.env.BASE_URL`(如 `/images/new/tj.svg`),请在宿主 `public/images/new/` 放置对应资源;业务按钮(如「机型统计」)通过 `useEventBus` 发事件,宿主需自行 `on('toggleBarChartControl', ...)` 监听。
133
-
134
- ## 可选业务钩子
135
-
136
- 若需光电引导、轨迹列表等业务能力,在应用启动时注入:
137
-
138
- ```js
139
- import { setDroneMapProvider, setOptGuideHandler } from 'huweili-cesium/config/hooks'
140
-
141
- setDroneMapProvider(() => myDroneMap)
142
- setOptGuideHandler((payload) => api.toOptGuide(payload))
143
- ```
144
-
145
- ## 发布到 npm(维护者)
146
-
147
- 项目根目录已配置 `.npmrc`(Token 授权,见 `.npmrc.example`),**无需执行 `npm login`**。安装依赖走 npmmirror 镜像,发布通过 `package.json` 中的 `publishConfig` 固定到 npm 官方源。
148
-
149
- ### 发布步骤
150
-
151
- 1. 修改 `package.json` 中的 `version`(须高于 npm 上已有版本)
152
- 2. 在项目根目录执行:
153
-
154
- ```bash
155
- npm publish
156
- ```
157
-
158
- ### 仅验证打包内容(不上传)
159
-
160
- ```bash
161
- npm publish --dry-run
162
- ```
163
-
164
- ### 本地打包预览
165
-
166
- ```bash
167
- npm pack
168
- # 会生成 huweili-cesium-x.y.z.tgz,解压检查是否包含全部 js
169
- ```
170
-
171
- ### 验证登录与最新版本
172
-
173
- ```bash
174
- npm whoami --registry=https://registry.npmjs.org/
175
- npm view huweili-cesium version --registry=https://registry.npmjs.org/
176
- ```
177
-
178
- ## 从 tzr 源目录同步更新
179
-
180
- ```bash
181
- cd huweili-cesium
182
- npm run sync
183
- # 同步后需重新修复 @/ 别名为包内相对路径(见 scripts)
184
- ```
185
-
186
- ## 地图与自定义工具栏
187
-
188
- 地图组件来自 npm 包 **`huweili-cesium`**,工具栏按钮在业务侧配置,不写在 `mapConfig.js` 里。
189
-
190
- ### 1. 前置配置(`constants.js` / `mapConfig.js`)
191
-
192
- `index.html` 中已按顺序引入:
193
-
194
- ```html
195
- <script src="/config/constants.js"></script>
196
- <script src="/config/mapConfig.js"></script>
197
- ```
198
-
199
- | 文件 | 作用 | 与地图组件的关系 |
200
- |------|------|------------------|
201
- | `public/config/constants.js` | `window.MapInstanceIds` 定义多地图 ID(如 `HOME: 'home-main-map'`) | `:map-id` 须与之一致,工具栏回调里的 `mapId` 也要传同一个值 |
202
- | `public/config/mapConfig.js` | `window.MapConfig`(中心点、2D/3D、底图列表、是否显示 Cesium 自带控件等) | 控制地图初始化;`control.homeButton: false` 时由自定义工具栏替代 |
203
-
204
- 在页面中引用常量(从 `runtimeConfig` 导入):
205
-
206
- ```js
207
- import { MapInstanceIds } from '@/config/runtimeConfig'
208
-
209
- const HOME_MAP_ID = MapInstanceIds?.HOME || 'home-main-map'
210
- ```
211
-
212
- ### 2. 页面引用 `CesiumMap`(首页示例)
213
-
214
- `src/views/home/indexnew.vue`:
215
-
216
- ```vue
217
- <template>
218
- <CesiumMap
219
- :map-id="HOME_MAP_ID"
220
- :toolbar-buttons="getHomeToolbarButtons({ mapId: HOME_MAP_ID })"
221
- @onload="mapOnLoad"
222
- />
223
- </template>
224
-
225
- <script setup>
226
- import CesiumMap from 'huweili-cesium'
227
- import { MapInstanceIds } from '@/config/runtimeConfig'
228
- import { getHomeToolbarButtons } from '@/utils/homeToolbarButtons'
229
-
230
- const HOME_MAP_ID = MapInstanceIds?.HOME || 'home-main-map'
231
- </script>
232
- ```
233
-
234
- - **`toolbar-buttons`**:传入整组按钮(首页不用包内默认按钮,因此不必再写 `show-default-toolbar`)
235
- - **`map-id`**:与 `constants.js` 里 `MapInstanceIds.HOME` 保持一致
236
-
237
- ### 3. 工具栏按钮配置(`src/utils/homeToolbarButtons.js`)
238
-
239
- 通用按钮(指北针、机型统计、回中心、2D/3D、缩放、底图、全屏)集中在此文件维护。
240
-
241
- 页面只需追加自己的按钮时,使用 `extra`:
242
-
243
- ```js
244
- import { useEventBus } from 'huweili-cesium/utils/useEventBus'
245
- import { getHomeToolbarButtons } from '@/utils/homeToolbarButtons'
246
-
247
- const { emit } = useEventBus()
248
-
249
- getHomeToolbarButtons({
250
- mapId: HOME_MAP_ID,
251
- extra: [
252
- {
253
- title: '导出',
254
- text: '导',
255
- onClick: () => emit('exportMap', {}),
256
- },
257
- ],
258
- })
259
- ```
260
-
261
- 按钮项字段说明:
262
-
263
- | 字段 | 说明 |
264
- |------|------|
265
- | `title` | 悬停提示 |
266
- | `text` / `iconSrc` | 文字或图标(二选一,图标放 `public/images/new/`) |
267
- | `isCompass: true` | 指北针专用 |
268
- | `onClick(viewer, button)` | 点击回调 |
269
-
270
- 「机型统计」等通过 `useEventBus` 发事件,页面需 `on('toggleBarChartControl', ...)` 监听。
271
-
272
- ### 4. 其他页面
273
-
274
- - 复用首页整套按钮:`getHomeToolbarButtons({ mapId: '你的 mapId' })`
275
- - 完全自定义:直接传数组给 `:toolbar-buttons="[...]"`
276
- - 地图加载后动态增删:在 `@onload` 回调里使用返回的 `toolbar.addToolbarButton(...)`
277
-
278
- 图标资源路径使用 `import.meta.env.BASE_URL`(如 `/jlap/images/new/xxx.svg`),请放在 `public/images/new/`。
279
-
280
- ## 目录结构
281
-
282
- ```
283
- huweili-cesium/
284
- ├── index.js # npm 主入口(默认导出 CesiumMap + 转发 js 模块)
285
- ├── index.vue # 地图 Vue 组件
286
- ├── components/ # 组件(如 wsIndicator)
287
- ├── js/ # 全部 JS 模块
288
- │ ├── basis.js
289
- │ ├── toolbar/
290
- │ ├── stores/
291
- │ ├── utils/
292
- │ ├── config/
293
- │ └── api/
294
- └── package.json
295
- ```
296
-
297
- ## 包含的文件清单(均在 `js/` 下)
298
-
299
- | 文件 | 说明 |
300
- |------|------|
301
- | js/basis.js | 地图基础操作 |
302
- | js/setPoint.js / js/movePoint.js | 点位与移动 |
303
- | js/setPath.js / js/movePath.js | 路径与轨迹 |
304
- | js/groundLink.js | 地面连接线 |
305
- | js/hemisphere.js | 半球区域 |
306
- | js/geometry.js | 几何图形 |
307
- | js/drawFence.js / js/drawFenceNew.js | 电子围栏 |
308
- | js/cardPool.js / js/labelDiv.js | 信息牌 |
309
- | js/clickHandler.js | 点击交互 |
310
- | js/tileProviders.js | 底图瓦片 |
311
- | js/customToolbarButtons.js | 工具栏 |
312
- | js/toolbar/* | 指南针、底图切换、缩放、全屏 |
313
- | js/droneRipple.js / js/qrCodeGenerator.js | 涟漪、二维码 |
314
-
315
- 另含 `js/stores/mapStore.js`、`js/utils/*`、`js/config/*`、`js/api/*` 等运行依赖。
1
+ # huweili-cesium
2
+
3
+ 基于 Cesium 的地图工具库。所有 **JS 模块** 位于包内 `js/` 目录(含 `toolbar`、`stores`、`utils`、`config`、`api` 子目录);根目录保留 `index.js`(npm 主入口)与 `index.vue`(地图组件)。
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ npm install huweili-cesium
9
+ ```
10
+
11
+ ### 对等依赖(需在项目中已安装)
12
+
13
+ - `cesium` 1.136.0
14
+ - `vue` ^3.3
15
+ - `pinia` ^2 或 ^3
16
+ - `mitt` 3
17
+ - `qrcode` 1.5
18
+
19
+ ## 使用前准备
20
+
21
+ 1. 在 HTML 中加载与宿主项目一致的 `constants.js`(定义 `window.DroneStatus`、`window.MapInstanceIds` 等),或自行赋值这些全局变量。
22
+ 2. 在 Vue 应用中 `app.use(pinia)`,地图组件初始化后调用各 `*Config()` 工厂函数。
23
+
24
+ ## 引入示例
25
+
26
+ ### JS 模块
27
+
28
+ ```js
29
+ // 主入口同时支持:默认导出组件 + 命名导出 JS 模块
30
+ import CesiumMap, { basicConfig, setPoint, movePointConfig } from 'huweili-cesium'
31
+
32
+ // 仅 JS 模块(不含 Vue 组件)可用子路径
33
+ import { basicConfig } from 'huweili-cesium/js'
34
+
35
+ // 或按文件引入
36
+ import { basicConfig } from 'huweili-cesium/basis'
37
+ import { hemisphereConfig } from 'huweili-cesium/hemisphere'
38
+ import { createCustomToolbarButtons } from 'huweili-cesium/customToolbarButtons'
39
+ ```
40
+
41
+ ### Vue 地图组件(开箱即用)
42
+
43
+ ```vue
44
+ <template>
45
+ <div class="map-page">
46
+ <CesiumMap map-id="default" @onload="onMapLoad" />
47
+ </div>
48
+ </template>
49
+
50
+ <script setup>
51
+ // 推荐:包主入口默认导出组件
52
+ import CesiumMap from 'huweili-cesium'
53
+ // 等价写法:
54
+ // import CesiumMap from 'huweili-cesium/index.vue'
55
+ // import CesiumMap from 'huweili-cesium/CesiumMap'
56
+
57
+ function onMapLoad({ map, center }) {
58
+ console.log('地图已加载', map, center)
59
+ }
60
+ </script>
61
+
62
+ <style scoped>
63
+ .map-page {
64
+ width: 100%;
65
+ height: 100vh;
66
+ }
67
+ </style>
68
+ ```
69
+
70
+ **Vite 宿主项目**需在 `vite.config` 中允许编译该依赖(否则 `.vue` 可能无法处理):
71
+
72
+ ```js
73
+ export default defineConfig({
74
+ optimizeDeps: {
75
+ include: ['huweili-cesium'],
76
+ },
77
+ })
78
+ ```
79
+
80
+ 组件 props:
81
+
82
+ | prop | 类型 | 默认 | 说明 |
83
+ |------|------|------|------|
84
+ | `mapId` | `string` | `'default'` | 多地图实例 ID,与 `mapStore` 对应 |
85
+ | `options` | `object` | — | 覆盖/合并 `MapConfig` 的配置 |
86
+
87
+ 事件:`@onload`,参数 `{ map, center, mapId, toolbar }`(`map` 为 Cesium `Viewer` 实例;`toolbar` 可在加载后动态增删按钮)。
88
+
89
+ ### 为何不用 Cesium 内置 2D 模式
90
+
91
+ Viewer 固定为 `SCENE3D`,业务上的「2D」是 **正交相机 + 俯视**(`basis.js` / `cameraInteraction.js`),不切换 `SCENE2D` / `COLUMBUS_VIEW`。简要优点:
92
+
93
+ - **2D/3D 切换更顺**:无场景变形(morph),透视与正交互换,缩放与锚点更易对齐(含工具栏切换、RTK 跟飞)。
94
+ - **渲染一致**:无人机、轨迹、围栏等与 3D 同一套规则,少踩 2D 投影下的显示差异。
95
+ - **交互可控**:2D 可锁定俯视、自定义滚轮缩放(正交宽度),避免与内置 2D 控制器行为不一致。
96
+ - **语义清晰**:`mapStore` 的 `2D`/`3D` 表示业务视角,不与 Cesium `SceneMode` 枚举混用。
97
+
98
+ 配置里 `scene.sceneMode: '2D'` 表示初始化俯视正交,而非启用 Cesium 平面地图模式。
99
+
100
+ ### 各项目自定义工具栏
101
+
102
+ **方式 1:组件 props(推荐)**
103
+
104
+ ```vue
105
+ <CesiumMap
106
+ map-id="default"
107
+ :show-default-toolbar="true"
108
+ :extra-toolbar-buttons="myExtraButtons"
109
+ />
110
+ ```
111
+
112
+ ```js
113
+ import { useEventBus } from 'huweili-cesium/utils/useEventBus'
114
+
115
+ const { emit } = useEventBus()
116
+
117
+ const myExtraButtons = [
118
+ {
119
+ title: '导出',
120
+ text: '导',
121
+ onClick: () => emit('exportMap', {}),
122
+ },
123
+ ]
124
+ ```
125
+
126
+ 完全不用内置默认按钮、自己定义一整组:
127
+
128
+ ```vue
129
+ <CesiumMap :toolbar-buttons="myToolbarButtons" />
130
+ ```
131
+
132
+ 内置默认按钮里的图标路径使用宿主项目的 `import.meta.env.BASE_URL`(如 `/images/new/tj.svg`),请在宿主 `public/images/new/` 放置对应资源;业务按钮(如「机型统计」)通过 `useEventBus` 发事件,宿主需自行 `on('toggleBarChartControl', ...)` 监听。
133
+
134
+ ## 可选业务钩子
135
+
136
+ 若需光电引导、轨迹列表等业务能力,在应用启动时注入:
137
+
138
+ ```js
139
+ import { setDroneMapProvider, setOptGuideHandler } from 'huweili-cesium/config/hooks'
140
+
141
+ setDroneMapProvider(() => myDroneMap)
142
+ setOptGuideHandler((payload) => api.toOptGuide(payload))
143
+ ```
144
+
145
+ ## 发布到 npm(维护者)
146
+
147
+ 项目根目录已配置 `.npmrc`(Token 授权,见 `.npmrc.example`),**无需执行 `npm login`**。安装依赖走 npmmirror 镜像,发布通过 `package.json` 中的 `publishConfig` 固定到 npm 官方源。
148
+
149
+ ### 发布步骤
150
+
151
+ 1. 修改 `package.json` 中的 `version`(须高于 npm 上已有版本)
152
+ 2. 在项目根目录执行:
153
+
154
+ ```bash
155
+ npm publish
156
+ ```
157
+
158
+ ### 仅验证打包内容(不上传)
159
+
160
+ ```bash
161
+ npm publish --dry-run
162
+ ```
163
+
164
+ ### 本地打包预览
165
+
166
+ ```bash
167
+ npm pack
168
+ # 会生成 huweili-cesium-x.y.z.tgz,解压检查是否包含全部 js
169
+ ```
170
+
171
+ ### 验证登录与最新版本
172
+
173
+ ```bash
174
+ npm whoami --registry=https://registry.npmjs.org/
175
+ npm view huweili-cesium version --registry=https://registry.npmjs.org/
176
+ ```
177
+
178
+ ## 从 tzr 源目录同步更新
179
+
180
+ ```bash
181
+ cd huweili-cesium
182
+ npm run sync
183
+ # 同步后需重新修复 @/ 别名为包内相对路径(见 scripts)
184
+ ```
185
+
186
+ ## 地图与自定义工具栏
187
+
188
+ 地图组件来自 npm 包 **`huweili-cesium`**,工具栏按钮在业务侧配置,不写在 `mapConfig.js` 里。
189
+
190
+ ### 1. 前置配置(`constants.js` / `mapConfig.js`)
191
+
192
+ `index.html` 中已按顺序引入:
193
+
194
+ ```html
195
+ <script src="/config/constants.js"></script>
196
+ <script src="/config/mapConfig.js"></script>
197
+ ```
198
+
199
+ | 文件 | 作用 | 与地图组件的关系 |
200
+ |------|------|------------------|
201
+ | `public/config/constants.js` | `window.MapInstanceIds` 定义多地图 ID(如 `HOME: 'home-main-map'`) | `:map-id` 须与之一致,工具栏回调里的 `mapId` 也要传同一个值 |
202
+ | `public/config/mapConfig.js` | `window.MapConfig`(中心点、2D/3D、底图列表、是否显示 Cesium 自带控件等) | 控制地图初始化;`control.homeButton: false` 时由自定义工具栏替代 |
203
+
204
+ 在页面中引用常量(从 `runtimeConfig` 导入):
205
+
206
+ ```js
207
+ import { MapInstanceIds } from '@/config/runtimeConfig'
208
+
209
+ const HOME_MAP_ID = MapInstanceIds?.HOME || 'home-main-map'
210
+ ```
211
+
212
+ ### 2. 页面引用 `CesiumMap`(首页示例)
213
+
214
+ `src/views/home/indexnew.vue`:
215
+
216
+ ```vue
217
+ <template>
218
+ <CesiumMap
219
+ :map-id="HOME_MAP_ID"
220
+ :toolbar-buttons="getHomeToolbarButtons({ mapId: HOME_MAP_ID })"
221
+ @onload="mapOnLoad"
222
+ />
223
+ </template>
224
+
225
+ <script setup>
226
+ import CesiumMap from 'huweili-cesium'
227
+ import { MapInstanceIds } from '@/config/runtimeConfig'
228
+ import { getHomeToolbarButtons } from '@/utils/homeToolbarButtons'
229
+
230
+ const HOME_MAP_ID = MapInstanceIds?.HOME || 'home-main-map'
231
+ </script>
232
+ ```
233
+
234
+ - **`toolbar-buttons`**:传入整组按钮(首页不用包内默认按钮,因此不必再写 `show-default-toolbar`)
235
+ - **`map-id`**:与 `constants.js` 里 `MapInstanceIds.HOME` 保持一致
236
+
237
+ ### 3. 工具栏按钮配置(`src/utils/homeToolbarButtons.js`)
238
+
239
+ 通用按钮(指北针、机型统计、回中心、2D/3D、缩放、底图、全屏)集中在此文件维护。
240
+
241
+ 页面只需追加自己的按钮时,使用 `extra`:
242
+
243
+ ```js
244
+ import { useEventBus } from 'huweili-cesium/utils/useEventBus'
245
+ import { getHomeToolbarButtons } from '@/utils/homeToolbarButtons'
246
+
247
+ const { emit } = useEventBus()
248
+
249
+ getHomeToolbarButtons({
250
+ mapId: HOME_MAP_ID,
251
+ extra: [
252
+ {
253
+ title: '导出',
254
+ text: '导',
255
+ onClick: () => emit('exportMap', {}),
256
+ },
257
+ ],
258
+ })
259
+ ```
260
+
261
+ 按钮项字段说明:
262
+
263
+ | 字段 | 说明 |
264
+ |------|------|
265
+ | `title` | 悬停提示 |
266
+ | `text` / `iconSrc` | 文字或图标(二选一,图标放 `public/images/new/`) |
267
+ | `isCompass: true` | 指北针专用 |
268
+ | `onClick(viewer, button)` | 点击回调 |
269
+
270
+ 「机型统计」等通过 `useEventBus` 发事件,页面需 `on('toggleBarChartControl', ...)` 监听。
271
+
272
+ ### 4. 其他页面
273
+
274
+ - 复用首页整套按钮:`getHomeToolbarButtons({ mapId: '你的 mapId' })`
275
+ - 完全自定义:直接传数组给 `:toolbar-buttons="[...]"`
276
+ - 地图加载后动态增删:在 `@onload` 回调里使用返回的 `toolbar.addToolbarButton(...)`
277
+
278
+ 图标资源路径使用 `import.meta.env.BASE_URL`(如 `/jlap/images/new/xxx.svg`),请放在 `public/images/new/`。
279
+
280
+ ## 目录结构
281
+
282
+ ```
283
+ huweili-cesium/
284
+ ├── index.js # npm 主入口(默认导出 CesiumMap + 转发 js 模块)
285
+ ├── index.vue # 地图 Vue 组件
286
+ ├── components/ # 组件(如 wsIndicator)
287
+ ├── js/ # 全部 JS 模块
288
+ │ ├── basis.js
289
+ │ ├── toolbar/
290
+ │ ├── stores/
291
+ │ ├── utils/
292
+ │ ├── config/
293
+ │ └── api/
294
+ └── package.json
295
+ ```
296
+
297
+ ## 包含的文件清单(均在 `js/` 下)
298
+
299
+ | 文件 | 说明 |
300
+ |------|------|
301
+ | js/basis.js | 地图基础操作 |
302
+ | js/setPoint.js / js/movePoint.js | 点位与移动 |
303
+ | js/setPath.js / js/movePath.js | 路径与轨迹 |
304
+ | js/groundLink.js | 地面连接线 |
305
+ | js/hemisphere.js | 半球区域 |
306
+ | js/geometry.js | 几何图形 |
307
+ | js/drawFence.js / js/drawFenceNew.js | 电子围栏 |
308
+ | js/cardPool.js / js/labelDiv.js | 信息牌 |
309
+ | js/clickHandler.js | 点击交互 |
310
+ | js/tileProviders.js | 底图瓦片 |
311
+ | js/customToolbarButtons.js | 工具栏 |
312
+ | js/toolbar/* | 指南针、底图切换、缩放、全屏 |
313
+ | js/droneRipple.js / js/qrCodeGenerator.js | 涟漪、二维码 |
314
+
315
+ 另含 `js/stores/mapStore.js`、`js/utils/*`、`js/config/*`、`js/api/*` 等运行依赖。
package/js/labelDiv.js CHANGED
@@ -10,6 +10,66 @@ const SVG_NS = 'http://www.w3.org/2000/svg';
10
10
  // 详情面板文字刷新最小间隔(毫秒),避免每帧跑逻辑
11
11
  const DRONE_INFO_UPDATE_MIN_MS = 1000;
12
12
 
13
+ /** @typedef {{ lng: string, lat: string, alt: string, speed: string, flyingHandName: string, flyingHandPhone: string, flyingHandPosition: string, frequencyBand: string, distance: string, receiveTime: string }} DroneInfoDisplay */
14
+
15
+ /**
16
+ * 将 getInfo 原始数据格式化为详情面板展示字段
17
+ * @param {Record<string, unknown>|null|undefined} info
18
+ * @returns {DroneInfoDisplay}
19
+ */
20
+ function formatDroneInfoDisplay(info) {
21
+ const parseLng = parseFloat(info?.lng);
22
+ const parseLat = parseFloat(info?.lat);
23
+ const lng = !isNaN(parseLng) ? parseLng.toFixed(4) : '--';
24
+ const lat = !isNaN(parseLat) ? parseLat.toFixed(4) : '--';
25
+ const alt = info?.height ?? '--';
26
+ const parseSpeed = parseFloat(info?.speed);
27
+ const speed = !isNaN(parseSpeed) ? parseSpeed.toFixed(1) : '--';
28
+ const flyingHandName = info?.flyingHandName ?? '--';
29
+ const flyingHandPhone = info?.flyingHandPhone ?? '--';
30
+ const frequencyBand = info?.frequencyBand ?? '--';
31
+ const receiveTime = info?.receiveTime ?? '--';
32
+ const groundLinkLng = info?.groundLinkLng ?? '--';
33
+ const groundLinkLat = info?.groundLinkLat ?? '--';
34
+ const flyingHandPosition =
35
+ groundLinkLng !== '--' && groundLinkLat !== '--'
36
+ ? `${groundLinkLng},${groundLinkLat}`
37
+ : (info?.flyingHandPosition ?? '--');
38
+ const parseDistance = parseFloat(String(info?.distance ?? '').replace(/[^\d.-]/g, ''));
39
+ const distance = Number.isFinite(parseDistance) ? parseDistance.toFixed(1) : '--';
40
+ return {
41
+ lng, lat, alt, speed, flyingHandName, flyingHandPhone,
42
+ flyingHandPosition, frequencyBand, distance, receiveTime
43
+ };
44
+ }
45
+
46
+ /**
47
+ * @param {DroneInfoDisplay} display
48
+ * @returns {string}
49
+ */
50
+ function buildInfoFingerprint(display) {
51
+ return `${display.lng}|${display.lat}|${display.alt}|${display.speed}|${display.flyingHandName}|${display.flyingHandPhone}|${display.frequencyBand}|${display.distance}|${display.receiveTime}`;
52
+ }
53
+
54
+ /**
55
+ * 优先使用最新数据,缺失字段回退到上次展示缓存
56
+ * @param {Record<string, unknown>|null|undefined} info
57
+ * @param {DroneInfoDisplay|null} cached
58
+ * @returns {DroneInfoDisplay}
59
+ */
60
+ function resolveInfoDisplay(info, cached) {
61
+ const fresh = formatDroneInfoDisplay(info);
62
+ if (!cached) return fresh;
63
+ /** @type {DroneInfoDisplay} */
64
+ const merged = { ...fresh };
65
+ for (const key of /** @type {(keyof DroneInfoDisplay)[]} */ (Object.keys(fresh))) {
66
+ if (fresh[key] === '--') {
67
+ merged[key] = cached[key];
68
+ }
69
+ }
70
+ return merged;
71
+ }
72
+
13
73
  /**
14
74
  * 各种标签div合集
15
75
  */
@@ -58,6 +118,8 @@ export function labelDiv() {
58
118
  let rafId = 0; // 是用来存储 requestAnimationFrame 的返回ID,用于管理无人机信息的实时刷新
59
119
  let lastInfoText = '';
60
120
  let lastInfoTick = 0;
121
+ /** @type {DroneInfoDisplay|null} */
122
+ let cachedInfoDisplay = null;
61
123
  let infoDiv = null;
62
124
  /** @type {Record<string, Element|null>|null} */
63
125
  let infoFieldEls = null;
@@ -129,47 +191,24 @@ export function labelDiv() {
129
191
  lastInfoTick = now;
130
192
 
131
193
  const info = labelItem.getInfo ? labelItem.getInfo() : null;
132
- // 处理经纬度(保留4位小数)
133
- const parseLng = parseFloat(info?.lng);
134
- const parseLat = parseFloat(info?.lat);
135
- const lng = !isNaN(parseLng) ? parseLng.toFixed(4) : '--';
136
- const lat = !isNaN(parseLat) ? parseLat.toFixed(4) : '--';
137
- const alt = info?.height ?? '--';
138
-
139
- // 处理速度(保留1位小数)
140
- const parseSpeed = parseFloat(info?.speed);
141
- const speed = !isNaN(parseSpeed) ? parseSpeed.toFixed(1) : '--';
142
- const flyingHandName = info?.flyingHandName ?? '--';
143
- const flyingHandPhone = info?.flyingHandPhone ?? '--';
144
- const frequencyBand = info?.frequencyBand ?? '--';
145
- const receiveTime = info?.receiveTime ?? '--';
146
- const groundLinkLng = info?.groundLinkLng ?? '--';
147
- const groundLinkLat = info?.groundLinkLat ?? '--';
148
- const flyingHandPosition =
149
- groundLinkLng !== '--' && groundLinkLat !== '--'
150
- ? `${groundLinkLng},${groundLinkLat}`
151
- : (info?.flyingHandPosition ?? '--');
152
-
153
- // 处理距离(保留1位小数,单位 m 在模板中单独展示)
154
- const parseDistance = parseFloat(String(info?.distance ?? '').replace(/[^\d.-]/g, ''))
155
- const distance = Number.isFinite(parseDistance) ? parseDistance.toFixed(1) : '--'
156
- const nextInfoText = `${lng}|${lat}|${alt}|${speed}|${flyingHandName}|${flyingHandPhone}|${frequencyBand}|${distance}|${receiveTime}`;
194
+ const display = resolveInfoDisplay(info, cachedInfoDisplay);
195
+ const nextInfoText = buildInfoFingerprint(display);
157
196
 
158
197
  if (nextInfoText !== lastInfoText && infoFieldEls) {
159
198
  const {
160
199
  lngEl, latEl, altEl, speedEl, flyingHandNameEl, flyingHandPhoneEl, flyingHandPositionEl, distanceEl, receiveTimeEl
161
200
  } = infoFieldEls;
162
- if (lngEl) lngEl.textContent = lng;
163
- if (latEl) latEl.textContent = lat;
164
- if (altEl) altEl.textContent = alt;
165
- if (receiveTimeEl) receiveTimeEl.textContent = receiveTime;
166
- if (speedEl) speedEl.textContent = String(speed);
167
- if (flyingHandNameEl) flyingHandNameEl.textContent = flyingHandName;
168
- if (flyingHandPhoneEl) flyingHandPhoneEl.textContent = flyingHandPhone;
169
- if (distanceEl) distanceEl.textContent = distance;
170
- if (receiveTimeEl) receiveTimeEl.textContent = receiveTime;
171
- if (flyingHandPositionEl) flyingHandPositionEl.textContent = flyingHandPosition;
201
+ if (lngEl) lngEl.textContent = display.lng;
202
+ if (latEl) latEl.textContent = display.lat;
203
+ if (altEl) altEl.textContent = display.alt;
204
+ if (receiveTimeEl) receiveTimeEl.textContent = display.receiveTime;
205
+ if (speedEl) speedEl.textContent = display.speed;
206
+ if (flyingHandNameEl) flyingHandNameEl.textContent = display.flyingHandName;
207
+ if (flyingHandPhoneEl) flyingHandPhoneEl.textContent = display.flyingHandPhone;
208
+ if (distanceEl) distanceEl.textContent = display.distance;
209
+ if (flyingHandPositionEl) flyingHandPositionEl.textContent = display.flyingHandPosition;
172
210
  lastInfoText = nextInfoText;
211
+ cachedInfoDisplay = display;
173
212
  }
174
213
 
175
214
  rafId = requestAnimationFrame(updateDroneInfo);
@@ -194,6 +233,11 @@ export function labelDiv() {
194
233
 
195
234
  // 统一使用一个 badge class,在 badge span 元素上设置背景图片
196
235
  const isUnknown = status === DroneStatus.UNKNOWN;
236
+ const initialInfo = labelItem.getInfo ? labelItem.getInfo() : null;
237
+ const initialDisplay = resolveInfoDisplay(initialInfo, cachedInfoDisplay);
238
+ const bandText = initialDisplay.frequencyBand !== '--'
239
+ ? initialDisplay.frequencyBand
240
+ : '2.4GHz、5.8GHz';
197
241
  detailDiv.innerHTML = `
198
242
  <div class="drone-detail-header">
199
243
  <span class="drone-badge"></span>
@@ -207,24 +251,24 @@ export function labelDiv() {
207
251
  </div>
208
252
  <div class="drone-detail-row">
209
253
  <span class="pilot-title">当前位置:</span>
210
- <span class="position"><span class="lng">-</span>, <span class="lat">-</span></span>
254
+ <span class="position"><span class="lng">${initialDisplay.lng}</span>, <span class="lat">${initialDisplay.lat}</span></span>
211
255
  </div>
212
256
 
213
257
  <div class="drone-detail-divider"></div>
214
258
 
215
259
  <div class="drone-detail-grid">
216
- <div><span class="pilot-title">高度:</span><span class="alt">-</span>m</div>
217
- <div><span class="pilot-title">速度:</span><span class="speed">-</span>m/s</div>
218
- <div><span class="pilot-title">距离:</span><span class="distance">-</span>m</div>
219
- ${!isUnknown ? '<div><span class="pilot-title">频段:</span><span class="band">2.4GHz、5.8GHz</span></div>' : ''}
260
+ <div><span class="pilot-title">高度:</span><span class="alt">${initialDisplay.alt}</span>m</div>
261
+ <div><span class="pilot-title">速度:</span><span class="speed">${initialDisplay.speed}</span>m/s</div>
262
+ <div><span class="pilot-title">距离:</span><span class="distance">${initialDisplay.distance}</span>m</div>
263
+ ${!isUnknown ? `<div><span class="pilot-title">频段:</span><span class="band">2.4GHz、5.8GHz</span></div>` : ''}
220
264
  </div>
221
265
  ${!isUnknown ? `
222
266
  <div class="drone-detail-divider"></div>
223
- <div class="drone-detail-row"><span class="pilot-title">姓名:</span><span class="pilot-name">张晓峰</span></div>
224
- <div class="drone-detail-row"><span class="pilot-title">电话:</span><span class="pilot-phone">18812563254</span></div>
225
- <div class="drone-detail-row"><span class="pilot-title">位置:</span><span class="pilot-position">-</span></div>
267
+ <div class="drone-detail-row"><span class="pilot-title">姓名:</span><span class="pilot-name">${initialDisplay.flyingHandName}</span></div>
268
+ <div class="drone-detail-row"><span class="pilot-title">电话:</span><span class="pilot-phone">${initialDisplay.flyingHandPhone}</span></div>
269
+ <div class="drone-detail-row"><span class="pilot-title">位置:</span><span class="pilot-position">${initialDisplay.flyingHandPosition}</span></div>
226
270
  ` : ''}
227
- <div class="drone-detail-row"><span class="pilot-title">时间:</span><span class="receive-time">-</span></div>
271
+ <div class="drone-detail-row"><span class="pilot-title">时间:</span><span class="receive-time">${initialDisplay.receiveTime}</span></div>
228
272
  </div>
229
273
  `;
230
274
 
@@ -296,6 +340,8 @@ export function labelDiv() {
296
340
  };
297
341
  }
298
342
 
343
+ lastInfoText = buildInfoFingerprint(initialDisplay);
344
+ cachedInfoDisplay = initialDisplay;
299
345
  lastInfoTick = 0;
300
346
  updateDroneInfo();
301
347
 
package/js/setPath.js CHANGED
@@ -1,126 +1,126 @@
1
- /**
2
- * 轨迹设置模块
3
- *
4
- * 提供在Cesium地图上设置无人机轨迹的功能
5
- *
6
- * @author huweili
7
- * @email czxyhuweili@163.com
8
- * @version 1.0.0
9
- */
10
- import * as Cesium from 'cesium'
11
- import { useMapStore } from './stores/mapStore.js'
12
- import { DroneStatus, DroneStatusMap, MapInstanceIds } from './config/index.js'
13
-
14
- export function setPath() {
15
- // 获取地图store实例
16
- const mapStore = useMapStore()
17
-
18
- /**
19
- * 创建无人机轨迹
20
- * @param pointId 无人机ID
21
- * @param startPosition 初始位置
22
- * @param status 无人机状态标识
23
- * @param mapId 地图实例ID
24
- * @returns 轨迹数据
25
- */
26
- const setDroneTrail = (options) => {
27
- const { pointId, startPosition, status = DroneStatus.WHITELIST, mapId } = options
28
- const map = mapStore.getMap(mapId)
29
- if (!map) return
30
-
31
- const trailId = `${pointId}_trail`
32
-
33
- // 如果轨迹已存在,直接返回
34
- if (mapStore.hasDroneTrail(pointId, mapId)) {
35
- console.log(`轨迹 ${trailId} 已存在`)
36
- return mapStore.getDroneTrail(pointId, mapId)
37
- }
38
-
39
- // 获取状态配置
40
- const statusConfig = DroneStatusMap[status]
41
- const trailColor = statusConfig ? Cesium.Color.fromCssColorString(statusConfig.trailColor) : Cesium.Color.fromCssColorString('rgba(0, 255, 145, 1)')
42
-
43
- // 轨迹实例
44
- const initialPosition = startPosition.clone()
45
- let trailData = {
46
- entity: null, // 轨迹实体
47
- positions: [{ position: initialPosition, timestamp: map.clock.currentTime }], // 轨迹位置数组,包含位置和时间戳
48
- renderPositions: [initialPosition], // Cesium渲染直接复用的坐标数组,避免每帧 map 生成新数组
49
- lastUpdateTime: map.clock.currentTime, // 最后更新时间
50
- isVisible: true, // 是否可见
51
- }
52
- trailData.entity = map.entities.add({
53
- id: trailId,
54
- name: `无人机轨迹:${pointId}`,
55
- show: true,
56
- polyline: {
57
- positions: new Cesium.CallbackProperty(() => {
58
- const trailData = mapStore.getDroneTrail(pointId, mapId)
59
- return trailData ? trailData.renderPositions : []
60
- }, false),
61
- width: 2,
62
- material: trailColor,
63
- arcType: Cesium.ArcType.NONE,// 直线连接 - 点与点之间用直线段连接
64
- clampToGround: false
65
- }
66
- })
67
-
68
- mapStore.setDroneTrail(pointId, trailData, mapId)
69
- // console.log(`创建轨迹: ${trailId}, 初始位置数: 1`)
70
- return trailData;
71
- }
72
-
73
- /**
74
- * 清除无人机轨迹
75
- */
76
- const clearDroneTrail = (droneId, mapId) => {
77
- const trailId = `${droneId}_trail`
78
- const trailData = mapStore.getDroneTrail(droneId, mapId)
79
-
80
- if (trailData) {
81
- const map = mapStore.getMap(mapId)
82
- if (map && trailData.entity) {
83
- // 先设置轨迹不可见
84
- // trailData.entity.show = false
85
- // 强制移除轨迹实体
86
- map.entities.remove(trailData.entity)
87
- trailData.entity = null
88
- }
89
- // 清空轨迹点
90
- if (trailData.positions) {
91
- trailData.positions = []
92
- }
93
- if (trailData.renderPositions) {
94
- trailData.renderPositions = []
95
- }
96
- // 设置轨迹不可见
97
- // trailData.isVisible = false
98
- // 从store中清除
99
- mapStore.clearDroneTrail(droneId, mapId)
100
- console.log(`已清除轨迹: ${trailId}`)
101
- }
102
- }
103
-
104
- /**
105
- * 显示/隐藏无人机轨迹
106
- * @param options 配置选项
107
- * @param options.pointId 点ID
108
- * @param options.visible 是否显示
109
- */
110
- const toggleDroneTrail = (options) => {
111
- const { pointId, visible, mapId } = options
112
- const trailId = `${pointId}_trail`
113
- const trailData = mapStore.getDroneTrail(pointId, mapId)
114
-
115
- if (trailData && trailData.entity) {
116
- trailData.entity.show = visible
117
- trailData.isVisible = visible
118
- }
119
- }
120
-
121
- return {
122
- setDroneTrail,
123
- clearDroneTrail,
124
- toggleDroneTrail
125
- }
1
+ /**
2
+ * 轨迹设置模块
3
+ *
4
+ * 提供在Cesium地图上设置无人机轨迹的功能
5
+ *
6
+ * @author huweili
7
+ * @email czxyhuweili@163.com
8
+ * @version 1.0.0
9
+ */
10
+ import * as Cesium from 'cesium'
11
+ import { useMapStore } from './stores/mapStore.js'
12
+ import { DroneStatus, DroneStatusMap, MapInstanceIds } from './config/index.js'
13
+
14
+ export function setPath() {
15
+ // 获取地图store实例
16
+ const mapStore = useMapStore()
17
+
18
+ /**
19
+ * 创建无人机轨迹
20
+ * @param pointId 无人机ID
21
+ * @param startPosition 初始位置
22
+ * @param status 无人机状态标识
23
+ * @param mapId 地图实例ID
24
+ * @returns 轨迹数据
25
+ */
26
+ const setDroneTrail = (options) => {
27
+ const { pointId, startPosition, status = DroneStatus.WHITELIST, mapId } = options
28
+ const map = mapStore.getMap(mapId)
29
+ if (!map) return
30
+
31
+ const trailId = `${pointId}_trail`
32
+
33
+ // 如果轨迹已存在,直接返回
34
+ if (mapStore.hasDroneTrail(pointId, mapId)) {
35
+ console.log(`轨迹 ${trailId} 已存在`)
36
+ return mapStore.getDroneTrail(pointId, mapId)
37
+ }
38
+
39
+ // 获取状态配置
40
+ const statusConfig = DroneStatusMap[status]
41
+ const trailColor = statusConfig ? Cesium.Color.fromCssColorString(statusConfig.trailColor) : Cesium.Color.fromCssColorString('rgba(0, 255, 145, 1)')
42
+
43
+ // 轨迹实例
44
+ const initialPosition = startPosition.clone()
45
+ let trailData = {
46
+ entity: null, // 轨迹实体
47
+ positions: [{ position: initialPosition, timestamp: map.clock.currentTime }], // 轨迹位置数组,包含位置和时间戳
48
+ renderPositions: [initialPosition], // Cesium渲染直接复用的坐标数组,避免每帧 map 生成新数组
49
+ lastUpdateTime: map.clock.currentTime, // 最后更新时间
50
+ isVisible: true, // 是否可见
51
+ }
52
+ trailData.entity = map.entities.add({
53
+ id: trailId,
54
+ name: `无人机轨迹:${pointId}`,
55
+ show: true,
56
+ polyline: {
57
+ positions: new Cesium.CallbackProperty(() => {
58
+ const trailData = mapStore.getDroneTrail(pointId, mapId)
59
+ return trailData ? trailData.renderPositions : []
60
+ }, false),
61
+ width: 2,
62
+ material: trailColor,
63
+ arcType: Cesium.ArcType.NONE,// 直线连接 - 点与点之间用直线段连接
64
+ clampToGround: false
65
+ }
66
+ })
67
+
68
+ mapStore.setDroneTrail(pointId, trailData, mapId)
69
+ // console.log(`创建轨迹: ${trailId}, 初始位置数: 1`)
70
+ return trailData;
71
+ }
72
+
73
+ /**
74
+ * 清除无人机轨迹
75
+ */
76
+ const clearDroneTrail = (droneId, mapId) => {
77
+ const trailId = `${droneId}_trail`
78
+ const trailData = mapStore.getDroneTrail(droneId, mapId)
79
+
80
+ if (trailData) {
81
+ const map = mapStore.getMap(mapId)
82
+ if (map && trailData.entity) {
83
+ // 先设置轨迹不可见
84
+ // trailData.entity.show = false
85
+ // 强制移除轨迹实体
86
+ map.entities.remove(trailData.entity)
87
+ trailData.entity = null
88
+ }
89
+ // 清空轨迹点
90
+ if (trailData.positions) {
91
+ trailData.positions = []
92
+ }
93
+ if (trailData.renderPositions) {
94
+ trailData.renderPositions = []
95
+ }
96
+ // 设置轨迹不可见
97
+ // trailData.isVisible = false
98
+ // 从store中清除
99
+ mapStore.clearDroneTrail(droneId, mapId)
100
+ console.log(`已清除轨迹: ${trailId}`)
101
+ }
102
+ }
103
+
104
+ /**
105
+ * 显示/隐藏无人机轨迹
106
+ * @param options 配置选项
107
+ * @param options.pointId 点ID
108
+ * @param options.visible 是否显示
109
+ */
110
+ const toggleDroneTrail = (options) => {
111
+ const { pointId, visible, mapId } = options
112
+ const trailId = `${pointId}_trail`
113
+ const trailData = mapStore.getDroneTrail(pointId, mapId)
114
+
115
+ if (trailData && trailData.entity) {
116
+ trailData.entity.show = visible
117
+ trailData.isVisible = visible
118
+ }
119
+ }
120
+
121
+ return {
122
+ setDroneTrail,
123
+ clearDroneTrail,
124
+ toggleDroneTrail
125
+ }
126
126
  }
@@ -1,94 +1,94 @@
1
- /**
2
- * 地图全屏控制器
3
- * 提供地图全屏切换功能
4
- *
5
- * @author huweili
6
- * @email czxyhuweili@163.com
7
- * @version 1.0.0
8
- */
9
-
10
- /**
11
- * 触发 Cesium 视图重新调整大小和渲染
12
- * 用于全屏切换后确保地图正确渲染
13
- * @param {import('cesium').Viewer} viewer - Cesium Viewer 实例
14
- */
15
- const resizeViewer = (viewer) => {
16
- requestAnimationFrame(() => {
17
- if (viewer && !viewer.isDestroyed()) {
18
- viewer.resize()
19
- viewer.scene.requestRender()
20
- }
21
- })
22
- }
23
-
24
- /**
25
- * 设置全屏按钮的图标
26
- * 根据全屏状态切换显示全屏图标或退出全屏图标
27
- * @param {HTMLButtonElement} button - 全屏按钮元素
28
- * @param {boolean} isFullscreen - 当前是否为全屏状态
29
- */
30
- const setFullscreenButtonIcon = (button, isFullscreen) => {
31
- const img = button.querySelector('img')
32
- if (!img) return
33
-
34
- img.src = `${import.meta.env.BASE_URL}/images/new/${isFullscreen ? 'nofullScreen' : 'fullScreen'}.svg`
35
- }
36
-
37
- /**
38
- * 切换地图全屏模式
39
- * 通过添加/移除 CSS 类实现地图容器全屏,而非浏览器全屏
40
- * @param {import('cesium').Viewer} viewer - Cesium Viewer 实例
41
- * @param {HTMLButtonElement} button - 触发全屏的按钮元素,用于更新按钮文字和标题
42
- */
43
- const toggleMapFullscreen = (viewer, button) => {
44
- const container = viewer.container
45
- const isFullscreen = container.classList.toggle('cesium-map-custom-fullscreen')
46
-
47
- button.title = isFullscreen ? '退出地图全屏' : '地图全屏'
48
- setFullscreenButtonIcon(button, isFullscreen)
49
- resizeViewer(viewer)
50
- }
51
-
52
- /**
53
- * 动态注入全屏样式到页面头部
54
- * 确保全屏时地图容器占满整个视口
55
- */
56
- const addMapFullscreenStyle = () => {
57
- const styleId = 'cesium-map-custom-fullscreen-style'
58
- if (document.getElementById(styleId)) return
59
-
60
- const style = document.createElement('style')
61
- style.id = styleId
62
- style.textContent = `
63
- .cesium-map-custom-fullscreen {
64
- position: fixed !important;
65
- inset: 0 !important;
66
- width: 100vw !important;
67
- height: 100vh !important;
68
- z-index: 2147483647 !important;
69
- background: #000 !important;
70
- }
71
-
72
- .cesium-map-custom-fullscreen .cesium-viewer,
73
- .cesium-map-custom-fullscreen .cesium-viewer-cesiumWidgetContainer,
74
- .cesium-map-custom-fullscreen .cesium-widget,
75
- .cesium-map-custom-fullscreen .cesium-widget canvas {
76
- width: 100% !important;
77
- height: 100% !important;
78
- }
79
- `
80
- document.head.appendChild(style)
81
- }
82
-
83
- /**
84
- * 创建全屏控制器
85
- * @returns {Object} 包含全屏操作方法的对象
86
- */
87
- export const createFullscreenController = () => {
88
- // 初始化时注入样式
89
- addMapFullscreenStyle()
90
-
91
- return {
92
- toggleMapFullscreen
93
- }
94
- }
1
+ /**
2
+ * 地图全屏控制器
3
+ * 提供地图全屏切换功能
4
+ *
5
+ * @author huweili
6
+ * @email czxyhuweili@163.com
7
+ * @version 1.0.0
8
+ */
9
+
10
+ /**
11
+ * 触发 Cesium 视图重新调整大小和渲染
12
+ * 用于全屏切换后确保地图正确渲染
13
+ * @param {import('cesium').Viewer} viewer - Cesium Viewer 实例
14
+ */
15
+ const resizeViewer = (viewer) => {
16
+ requestAnimationFrame(() => {
17
+ if (viewer && !viewer.isDestroyed()) {
18
+ viewer.resize()
19
+ viewer.scene.requestRender()
20
+ }
21
+ })
22
+ }
23
+
24
+ /**
25
+ * 设置全屏按钮的图标
26
+ * 根据全屏状态切换显示全屏图标或退出全屏图标
27
+ * @param {HTMLButtonElement} button - 全屏按钮元素
28
+ * @param {boolean} isFullscreen - 当前是否为全屏状态
29
+ */
30
+ const setFullscreenButtonIcon = (button, isFullscreen) => {
31
+ const img = button.querySelector('img')
32
+ if (!img) return
33
+
34
+ img.src = `${import.meta.env.BASE_URL}/images/new/${isFullscreen ? 'nofullScreen' : 'fullScreen'}.svg`
35
+ }
36
+
37
+ /**
38
+ * 切换地图全屏模式
39
+ * 通过添加/移除 CSS 类实现地图容器全屏,而非浏览器全屏
40
+ * @param {import('cesium').Viewer} viewer - Cesium Viewer 实例
41
+ * @param {HTMLButtonElement} button - 触发全屏的按钮元素,用于更新按钮文字和标题
42
+ */
43
+ const toggleMapFullscreen = (viewer, button) => {
44
+ const container = viewer.container
45
+ const isFullscreen = container.classList.toggle('cesium-map-custom-fullscreen')
46
+
47
+ button.title = isFullscreen ? '退出地图全屏' : '地图全屏'
48
+ setFullscreenButtonIcon(button, isFullscreen)
49
+ resizeViewer(viewer)
50
+ }
51
+
52
+ /**
53
+ * 动态注入全屏样式到页面头部
54
+ * 确保全屏时地图容器占满整个视口
55
+ */
56
+ const addMapFullscreenStyle = () => {
57
+ const styleId = 'cesium-map-custom-fullscreen-style'
58
+ if (document.getElementById(styleId)) return
59
+
60
+ const style = document.createElement('style')
61
+ style.id = styleId
62
+ style.textContent = `
63
+ .cesium-map-custom-fullscreen {
64
+ position: fixed !important;
65
+ inset: 0 !important;
66
+ width: 100vw !important;
67
+ height: 100vh !important;
68
+ z-index: 2147483647 !important;
69
+ background: #000 !important;
70
+ }
71
+
72
+ .cesium-map-custom-fullscreen .cesium-viewer,
73
+ .cesium-map-custom-fullscreen .cesium-viewer-cesiumWidgetContainer,
74
+ .cesium-map-custom-fullscreen .cesium-widget,
75
+ .cesium-map-custom-fullscreen .cesium-widget canvas {
76
+ width: 100% !important;
77
+ height: 100% !important;
78
+ }
79
+ `
80
+ document.head.appendChild(style)
81
+ }
82
+
83
+ /**
84
+ * 创建全屏控制器
85
+ * @returns {Object} 包含全屏操作方法的对象
86
+ */
87
+ export const createFullscreenController = () => {
88
+ // 初始化时注入样式
89
+ addMapFullscreenStyle()
90
+
91
+ return {
92
+ toggleMapFullscreen
93
+ }
94
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "huweili-cesium",
3
- "version": "1.2.84",
3
+ "version": "1.2.86",
4
4
  "description": "基于 Cesium 的地图工具库(无人机态势、轨迹、围栏、工具栏等)",
5
5
  "type": "module",
6
6
  "main": "./index.js",