@xingm/vmap-cesium-toolbar 0.0.1-beta.2 → 0.0.1-beta.4

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/dist/index.js CHANGED
@@ -11,14 +11,25 @@ class m {
11
11
  tempPositions = [];
12
12
  tempEntities = [];
13
13
  // 临时实体,用于绘制过程中
14
+ tempLabelEntities = [];
15
+ // 临时标签实体
14
16
  finishedEntities = [];
15
17
  // 已完成的实体
18
+ finishedLabelEntities = [];
19
+ // 已完成的标签实体
20
+ finishedPointEntities = [];
21
+ // 已完成的点实体
22
+ publicEntities = [];
23
+ // 通过公共方法创建的实体
24
+ _doubleClickPending = !1;
25
+ // 双击判断
16
26
  // 事件处理器
17
27
  screenSpaceEventHandler = null;
18
28
  // 回调函数
19
29
  onDrawStartCallback = null;
20
30
  onDrawEndCallback = null;
21
31
  onEntityRemovedCallback = null;
32
+ offsetHeight = 2;
22
33
  /**
23
34
  * 构造函数
24
35
  * @param viewer Cesium Viewer 实例
@@ -26,7 +37,29 @@ class m {
26
37
  constructor(e) {
27
38
  if (!e || !(e instanceof n.Viewer))
28
39
  throw new Error("Invalid Cesium Viewer instance provided.");
29
- this.viewer = e, this.scene = e.scene, this.entities = e.entities, this.scene.globe.depthTestAgainstTerrain = !0;
40
+ this.viewer = e, this.scene = e.scene, this.entities = e.entities, this.updateOffsetHeight(), this.scene.morphComplete.addEventListener(() => {
41
+ this.updateOffsetHeight();
42
+ }), this.scene.globe.depthTestAgainstTerrain = !0;
43
+ }
44
+ /**
45
+ * 根据场景模式更新偏移高度
46
+ */
47
+ updateOffsetHeight() {
48
+ this.scene.mode === n.SceneMode.SCENE3D ? this.offsetHeight = 100 : this.offsetHeight = 0;
49
+ }
50
+ /**
51
+ * 手动设置偏移高度
52
+ * @param height 偏移高度(米)
53
+ */
54
+ setOffsetHeight(e) {
55
+ this.offsetHeight = e;
56
+ }
57
+ /**
58
+ * 获取当前偏移高度
59
+ * @returns 当前偏移高度(米)
60
+ */
61
+ getOffsetHeight() {
62
+ return this.offsetHeight;
30
63
  }
31
64
  clearFrustum() {
32
65
  this.frustumPrimitives.forEach((e) => {
@@ -37,7 +70,7 @@ class m {
37
70
  drawFrustum(e = {}) {
38
71
  try {
39
72
  this.clearFrustum();
40
- const t = Math.max(1, Math.min(179, e.fov || 60)), i = Math.max(0.1, e.aspectRatio || 1), r = Math.max(0.1, e.near || 1), s = Math.max(r + 1, e.far || 1e3), o = e.position || this.viewer.camera.positionWC, a = e.orientation || n.Quaternion.fromRotationMatrix(
73
+ const t = Math.max(1, Math.min(179, e.fov || 60)), i = Math.max(0.1, e.aspectRatio || 1), s = Math.max(0.1, e.near || 1), o = Math.max(s + 1, e.far || 1e3), a = e.position || this.viewer.camera.positionWC, r = e.orientation || n.Quaternion.fromRotationMatrix(
41
74
  n.Matrix4.getRotation(
42
75
  this.viewer.camera.transform,
43
76
  new n.Matrix3()
@@ -45,30 +78,30 @@ class m {
45
78
  ), l = new n.PerspectiveFrustum({
46
79
  fov: n.Math.toRadians(t),
47
80
  aspectRatio: i,
48
- near: r,
49
- far: s
81
+ near: s,
82
+ far: o
50
83
  }), c = new n.FrustumGeometry({
51
84
  frustum: l,
52
- origin: o,
53
- orientation: a,
85
+ origin: a,
86
+ orientation: r,
54
87
  vertexFormat: n.VertexFormat.POSITION_ONLY
55
- }), d = new n.GeometryInstance({
88
+ }), h = new n.GeometryInstance({
56
89
  geometry: c,
57
90
  attributes: {
58
91
  color: n.ColorGeometryInstanceAttribute.fromColor(
59
92
  e.fillColor || new n.Color(1, 0, 0, 0.3)
60
93
  )
61
94
  }
62
- }), u = new n.Primitive({
63
- geometryInstances: d,
95
+ }), d = new n.Primitive({
96
+ geometryInstances: h,
64
97
  appearance: new n.PerInstanceColorAppearance({
65
98
  closed: !0,
66
99
  flat: !0
67
100
  })
68
101
  }), g = new n.FrustumOutlineGeometry({
69
102
  frustum: l,
70
- origin: o,
71
- orientation: a
103
+ origin: a,
104
+ orientation: r
72
105
  }), f = new n.GeometryInstance({
73
106
  geometry: g,
74
107
  attributes: {
@@ -83,8 +116,8 @@ class m {
83
116
  flat: !0
84
117
  })
85
118
  });
86
- this.viewer.scene.primitives.add(u), this.viewer.scene.primitives.add(p), this.frustumPrimitives.push(u, p), e.onRightClick && this.screenSpaceEventHandler && this.screenSpaceEventHandler.setInputAction((C) => {
87
- C.position && e.onRightClick && e.onRightClick(o);
119
+ this.viewer.scene.primitives.add(d), this.viewer.scene.primitives.add(p), this.frustumPrimitives.push(d, p), e.onRightClick && this.screenSpaceEventHandler && this.screenSpaceEventHandler.setInputAction((C) => {
120
+ C.position && e.onRightClick && e.onRightClick(a);
88
121
  }, n.ScreenSpaceEventType.RIGHT_CLICK);
89
122
  } catch (t) {
90
123
  console.error("绘制视锥体时发生错误:", t), this.clearFrustum();
@@ -124,6 +157,10 @@ class m {
124
157
  ), this.screenSpaceEventHandler.setInputAction(
125
158
  (t) => {
126
159
  if (!this.isDrawing) return;
160
+ if (this._doubleClickPending) {
161
+ this._doubleClickPending = !1;
162
+ return;
163
+ }
127
164
  const i = this.pickGlobePosition(t.position);
128
165
  i && this.addPoint(i);
129
166
  },
@@ -145,7 +182,7 @@ class m {
145
182
  n.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
146
183
  ), this.screenSpaceEventHandler.setInputAction(
147
184
  (t) => {
148
- this.isDrawing && (this.finishDrawing(), this.viewer.cesiumWidget.screenSpaceEventHandler.setInputAction(
185
+ this.isDrawing && (this._doubleClickPending = !0, this.finishDrawing(), e && this.viewer.cesiumWidget.screenSpaceEventHandler.setInputAction(
149
186
  e,
150
187
  n.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
151
188
  ));
@@ -161,9 +198,9 @@ class m {
161
198
  pickGlobePosition(e) {
162
199
  const t = this.viewer.camera.getPickRay(e);
163
200
  if (t) {
164
- const r = this.scene.globe.pick(t, this.scene);
165
- if (n.defined(r))
166
- return r;
201
+ const s = this.scene.globe.pick(t, this.scene);
202
+ if (n.defined(s))
203
+ return s;
167
204
  }
168
205
  return this.viewer.camera.pickEllipsoid(
169
206
  e,
@@ -176,29 +213,56 @@ class m {
176
213
  */
177
214
  addPoint(e) {
178
215
  this.tempPositions.push(e.clone());
179
- const t = this.entities.add({
180
- position: e.clone(),
216
+ const t = n.Cartographic.fromCartesian(e), i = n.Cartesian3.fromRadians(
217
+ t.longitude,
218
+ t.latitude,
219
+ (t.height || 0) + (this.drawMode !== "line" ? 0 : this.offsetHeight)
220
+ ), s = this.entities.add({
221
+ position: i,
181
222
  point: {
182
- pixelSize: 5,
223
+ pixelSize: 8,
183
224
  color: n.Color.RED,
184
225
  outlineColor: n.Color.WHITE,
185
- outlineWidth: 2,
186
- heightReference: n.HeightReference.CLAMP_TO_GROUND
226
+ outlineWidth: 3,
227
+ heightReference: n.HeightReference.RELATIVE_TO_GROUND,
228
+ scaleByDistance: new n.NearFarScalar(150, 1, 15e6, 0.5)
187
229
  }
188
230
  });
189
- this.tempEntities.push(t), this.updateDrawingEntity();
231
+ this.tempEntities.push(s), this.updateDrawingEntity();
190
232
  }
191
233
  /**
192
234
  * 删除最后一个添加的点及其相关的临时实体
193
235
  */
194
236
  removeLastPoint() {
195
- if (this.tempPositions.length > 0) {
196
- this.tempPositions.pop();
197
- const e = this.tempEntities.pop();
237
+ this.tempPositions.length > 0 && (this.tempPositions.pop(), this.tempEntities.forEach((e) => {
198
238
  e && this.entities.remove(e);
199
- const t = this.tempEntities.pop();
200
- t && this.entities.remove(t), this.updateDrawingEntity();
201
- }
239
+ }), this.tempEntities = [], this.tempLabelEntities.forEach((e) => {
240
+ e && this.entities.remove(e);
241
+ }), this.tempLabelEntities = [], this.recreateRemainingEntities());
242
+ }
243
+ /**
244
+ * 重新创建剩余的点实体和绘制实体
245
+ * 用于右键删除点后的重建
246
+ */
247
+ recreateRemainingEntities() {
248
+ this.tempPositions.forEach((e) => {
249
+ const t = n.Cartographic.fromCartesian(e), i = n.Cartesian3.fromRadians(
250
+ t.longitude,
251
+ t.latitude,
252
+ (t.height || 0) + this.offsetHeight
253
+ ), s = this.entities.add({
254
+ position: i,
255
+ point: {
256
+ pixelSize: 8,
257
+ color: n.Color.RED,
258
+ outlineColor: n.Color.WHITE,
259
+ outlineWidth: 3,
260
+ heightReference: n.HeightReference.RELATIVE_TO_GROUND,
261
+ scaleByDistance: new n.NearFarScalar(150, 1, 15e6, 0.5)
262
+ }
263
+ });
264
+ this.tempEntities.push(s);
265
+ }), this.updateDrawingEntity();
202
266
  }
203
267
  /**
204
268
  * 更新预览线/面
@@ -212,79 +276,160 @@ class m {
212
276
  * @param previewPoint 可选的预览点,用于显示动态效果
213
277
  */
214
278
  updateDrawingEntity(e) {
215
- this.tempEntities.forEach((r) => {
216
- r && (r.polyline || r.polygon || r.label) && this.entities.remove(r);
217
- }), this.tempEntities = [];
218
- const t = [...this.tempPositions];
219
- if (e && t.push(e), t.length < 2) return;
220
- let i;
279
+ const t = [];
280
+ this.tempEntities.forEach((o) => {
281
+ o && (o.polyline || o.polygon || o.rectangle) && t.push(o);
282
+ }), t.forEach((o) => {
283
+ this.entities.remove(o);
284
+ const a = this.tempEntities.indexOf(o);
285
+ a > -1 && this.tempEntities.splice(a, 1);
286
+ }), this.tempLabelEntities.forEach((o) => {
287
+ o && this.entities.remove(o);
288
+ }), this.tempLabelEntities = [];
289
+ const i = [...this.tempPositions];
290
+ if (e && i.push(e), i.length < 2) return;
291
+ let s;
221
292
  if (this.drawMode === "line") {
222
- i = this.entities.add({
223
- polyline: {
224
- positions: t,
225
- width: 3,
226
- material: n.Color.YELLOW,
227
- clampToGround: !0
293
+ if (this.offsetHeight > 0) {
294
+ const o = i.map((a) => {
295
+ const r = n.Cartographic.fromCartesian(a);
296
+ return n.Cartesian3.fromRadians(
297
+ r.longitude,
298
+ r.latitude,
299
+ (r.height || 0) + this.offsetHeight
300
+ );
301
+ });
302
+ s = this.entities.add({
303
+ polyline: {
304
+ positions: o,
305
+ width: 5,
306
+ material: n.Color.YELLOW,
307
+ clampToGround: !1
308
+ }
309
+ });
310
+ } else
311
+ s = this.entities.add({
312
+ polyline: {
313
+ positions: i,
314
+ width: 5,
315
+ material: n.Color.YELLOW,
316
+ clampToGround: !0
317
+ }
318
+ });
319
+ this.tempEntities.push(s);
320
+ for (let o = 0; o < i.length - 1; o++) {
321
+ const a = i[o], r = i[o + 1], l = n.Cartesian3.distance(a, r);
322
+ if (l > 5) {
323
+ const c = n.Cartesian3.midpoint(
324
+ a,
325
+ r,
326
+ new n.Cartesian3()
327
+ ), h = o % 2 === 0 ? -25 : 25, d = this.entities.add({
328
+ position: c,
329
+ label: {
330
+ text: `${l.toFixed(2)} m`,
331
+ font: "16px Arial",
332
+ fillColor: n.Color.WHITE,
333
+ outlineColor: n.Color.BLACK,
334
+ outlineWidth: 3,
335
+ style: n.LabelStyle.FILL_AND_OUTLINE,
336
+ pixelOffset: new n.Cartesian2(0, h),
337
+ heightReference: this.offsetHeight > 0 ? n.HeightReference.RELATIVE_TO_GROUND : n.HeightReference.CLAMP_TO_GROUND,
338
+ scale: 1,
339
+ showBackground: !0,
340
+ backgroundColor: n.Color.BLACK.withAlpha(0.8),
341
+ backgroundPadding: new n.Cartesian2(6, 3)
342
+ }
343
+ });
344
+ this.tempLabelEntities.push(d);
345
+ }
346
+ }
347
+ if (i.length > 1) {
348
+ let o = 0;
349
+ for (let l = 1; l < i.length; l++)
350
+ o += n.Cartesian3.distance(
351
+ i[l - 1],
352
+ i[l]
353
+ );
354
+ let a = i[i.length - 1];
355
+ if (this.offsetHeight > 0) {
356
+ const l = n.Cartographic.fromCartesian(a);
357
+ a = n.Cartesian3.fromRadians(
358
+ l.longitude,
359
+ l.latitude,
360
+ (l.height || 0) + this.offsetHeight
361
+ );
228
362
  }
229
- }), this.tempEntities.push(i);
230
- for (let r = 0; r < t.length - 1; r++) {
231
- const s = t[r], o = t[r + 1], a = n.Cartesian3.distance(s, o), l = n.Cartesian3.midpoint(s, o, new n.Cartesian3()), c = this.entities.add({
232
- position: l,
363
+ const r = this.entities.add({
364
+ position: a,
233
365
  label: {
234
- text: `${a.toFixed(2)} m`,
235
- font: "12px sans-serif",
236
- fillColor: n.Color.CYAN,
366
+ text: `总长: ${o.toFixed(2)} m`,
367
+ font: "18px Arial",
368
+ fillColor: n.Color.YELLOW,
237
369
  outlineColor: n.Color.BLACK,
238
- outlineWidth: 1,
370
+ outlineWidth: 3,
239
371
  style: n.LabelStyle.FILL_AND_OUTLINE,
240
- pixelOffset: new n.Cartesian2(0, -10),
241
- heightReference: n.HeightReference.CLAMP_TO_GROUND
372
+ pixelOffset: new n.Cartesian2(0, 40),
373
+ heightReference: this.offsetHeight > 0 ? n.HeightReference.NONE : n.HeightReference.CLAMP_TO_GROUND,
374
+ scale: 1,
375
+ showBackground: !0,
376
+ backgroundColor: n.Color.BLACK.withAlpha(0.9),
377
+ backgroundPadding: new n.Cartesian2(8, 4)
242
378
  }
243
379
  });
244
- this.tempEntities.push(c);
380
+ this.tempLabelEntities.push(r);
245
381
  }
246
- if (t.length > 1) {
247
- let r = 0;
248
- for (let o = 1; o < t.length; o++)
249
- r += n.Cartesian3.distance(t[o - 1], t[o]);
250
- const s = this.entities.add({
251
- position: t[t.length - 1],
252
- label: {
253
- text: `总长: ${r.toFixed(2)} m`,
254
- font: "14px sans-serif",
255
- fillColor: n.Color.WHITE,
256
- outlineColor: n.Color.BLACK,
382
+ } else if (this.drawMode === "polygon")
383
+ if (this.offsetHeight > 0) {
384
+ const o = i.map((a) => {
385
+ const r = n.Cartographic.fromCartesian(a);
386
+ return n.Cartesian3.fromRadians(
387
+ r.longitude,
388
+ r.latitude,
389
+ (r.height || 0) + this.offsetHeight
390
+ );
391
+ });
392
+ s = this.entities.add({
393
+ polygon: {
394
+ hierarchy: new n.CallbackProperty(() => new n.PolygonHierarchy(o), !1),
395
+ material: n.Color.LIGHTGREEN.withAlpha(0.3),
396
+ // 淡绿色填充
397
+ outline: !0,
398
+ outlineColor: n.Color.GREEN,
399
+ outlineWidth: 2,
400
+ heightReference: n.HeightReference.NONE
401
+ }
402
+ });
403
+ } else
404
+ s = this.entities.add({
405
+ polygon: {
406
+ hierarchy: new n.CallbackProperty(() => new n.PolygonHierarchy(i), !1),
407
+ material: n.Color.LIGHTGREEN.withAlpha(0.3),
408
+ // 淡绿色填充
409
+ outline: !0,
410
+ outlineColor: n.Color.GREEN,
257
411
  outlineWidth: 2,
258
- style: n.LabelStyle.FILL_AND_OUTLINE,
259
- pixelOffset: new n.Cartesian2(0, 20),
260
412
  heightReference: n.HeightReference.CLAMP_TO_GROUND
261
413
  }
262
414
  });
263
- this.tempEntities.push(s);
264
- }
265
- } else if (this.drawMode === "polygon")
266
- i = this.entities.add({
267
- polygon: {
268
- hierarchy: new n.CallbackProperty(() => new n.PolygonHierarchy(t), !1),
269
- material: n.Color.LIGHTGREEN.withAlpha(0.3),
270
- // 淡绿色填充
271
- outline: !0,
272
- outlineColor: n.Color.GREEN,
273
- outlineWidth: 2,
274
- heightReference: n.HeightReference.CLAMP_TO_GROUND
415
+ else if (this.drawMode === "rectangle" && i.length >= 2) {
416
+ const o = this.calculateRectangle(i[0], i[1]);
417
+ this.offsetHeight > 0 ? s = this.entities.add({
418
+ rectangle: {
419
+ coordinates: o,
420
+ material: n.Color.GREEN.withAlpha(0.5),
421
+ heightReference: n.HeightReference.NONE,
422
+ extrudedHeight: this.offsetHeight
275
423
  }
276
- });
277
- else if (this.drawMode === "rectangle" && t.length >= 2) {
278
- const r = this.calculateRectangle(t[0], t[1]);
279
- i = this.entities.add({
424
+ }) : s = this.entities.add({
280
425
  rectangle: {
281
- coordinates: r,
426
+ coordinates: o,
282
427
  material: n.Color.GREEN.withAlpha(0.5),
283
428
  heightReference: n.HeightReference.CLAMP_TO_GROUND
284
429
  }
285
430
  });
286
431
  }
287
- i && this.tempEntities.push(i);
432
+ s && this.tempEntities.push(s);
288
433
  }
289
434
  /**
290
435
  * 完成当前绘制操作
@@ -296,68 +441,74 @@ class m {
296
441
  }
297
442
  let e = null;
298
443
  const t = this.tempPositions.map((i) => i.clone());
299
- if (this.drawMode === "line") {
300
- e = this.entities.add({
301
- name: "绘制的线",
302
- polyline: {
303
- positions: t,
304
- width: 3,
305
- material: n.Color.YELLOW,
306
- clampToGround: !0
307
- }
308
- });
309
- for (let i = 0; i < t.length - 1; i++) {
310
- const r = t[i], s = t[i + 1], o = n.Cartesian3.distance(r, s), a = n.Cartesian3.midpoint(r, s, new n.Cartesian3());
311
- this.entities.add({
312
- position: a,
313
- label: {
314
- text: `${o.toFixed(2)} m`,
315
- font: "12px sans-serif",
316
- fillColor: n.Color.CYAN,
317
- outlineColor: n.Color.BLACK,
318
- outlineWidth: 1,
319
- style: n.LabelStyle.FILL_AND_OUTLINE,
320
- pixelOffset: new n.Cartesian2(0, -10),
321
- heightReference: n.HeightReference.CLAMP_TO_GROUND
444
+ if (this.drawMode === "line")
445
+ if (this.offsetHeight > 0) {
446
+ const i = t.map((s) => {
447
+ const o = n.Cartographic.fromCartesian(s);
448
+ return n.Cartesian3.fromRadians(
449
+ o.longitude,
450
+ o.latitude,
451
+ (o.height || 0) + this.offsetHeight
452
+ );
453
+ });
454
+ e = this.entities.add({
455
+ name: "绘制的线",
456
+ polyline: {
457
+ positions: i,
458
+ width: 5,
459
+ material: n.Color.YELLOW,
460
+ clampToGround: !1
322
461
  }
323
462
  });
324
- }
325
- if (t.length > 1) {
326
- let i = 0;
327
- for (let r = 1; r < t.length; r++)
328
- i += n.Cartesian3.distance(t[r - 1], t[r]);
329
- this.entities.add({
330
- position: t[t.length - 1],
331
- label: {
332
- text: `总长: ${i.toFixed(2)} m`,
333
- font: "14px sans-serif",
334
- fillColor: n.Color.WHITE,
335
- outlineColor: n.Color.BLACK,
463
+ } else
464
+ e = this.entities.add({
465
+ name: "绘制的线",
466
+ polyline: {
467
+ positions: t,
468
+ width: 5,
469
+ material: n.Color.YELLOW,
470
+ clampToGround: !0
471
+ }
472
+ });
473
+ else if (this.drawMode === "polygon") {
474
+ if (this.offsetHeight > 0) {
475
+ const s = t.map((o) => {
476
+ const a = n.Cartographic.fromCartesian(o);
477
+ return n.Cartesian3.fromRadians(
478
+ a.longitude,
479
+ a.latitude,
480
+ (a.height || 0) + this.offsetHeight
481
+ );
482
+ });
483
+ e = this.entities.add({
484
+ name: "绘制的多边形区域",
485
+ polygon: {
486
+ hierarchy: new n.PolygonHierarchy(s),
487
+ material: n.Color.LIGHTGREEN.withAlpha(0.3),
488
+ // 淡绿色填充
489
+ outline: !0,
490
+ outlineColor: n.Color.GREEN,
491
+ outlineWidth: 2,
492
+ heightReference: n.HeightReference.NONE
493
+ }
494
+ });
495
+ } else
496
+ e = this.entities.add({
497
+ name: "绘制的多边形区域",
498
+ polygon: {
499
+ hierarchy: new n.PolygonHierarchy(t),
500
+ material: n.Color.LIGHTGREEN.withAlpha(0.3),
501
+ // 淡绿色填充
502
+ outline: !0,
503
+ outlineColor: n.Color.GREEN,
336
504
  outlineWidth: 2,
337
- style: n.LabelStyle.FILL_AND_OUTLINE,
338
- pixelOffset: new n.Cartesian2(0, 20),
339
505
  heightReference: n.HeightReference.CLAMP_TO_GROUND
340
506
  }
341
507
  });
342
- }
343
- } else if (this.drawMode === "polygon") {
344
- e = this.entities.add({
345
- name: "绘制的多边形区域",
346
- polygon: {
347
- hierarchy: new n.PolygonHierarchy(t),
348
- material: n.Color.LIGHTGREEN.withAlpha(0.3),
349
- // 淡绿色填充
350
- outline: !0,
351
- outlineColor: n.Color.GREEN,
352
- outlineWidth: 2,
353
- heightReference: n.HeightReference.CLAMP_TO_GROUND
354
- }
355
- });
356
508
  const i = this.calculatePolygonArea(t);
357
509
  if (i > 0) {
358
- const r = this.calculatePolygonCenter(t);
359
- this.entities.add({
360
- position: r,
510
+ const s = this.calculatePolygonCenter(t), o = this.entities.add({
511
+ position: s,
361
512
  label: {
362
513
  text: `面积: ${i.toFixed(2)} km²`,
363
514
  font: "14px sans-serif",
@@ -369,10 +520,19 @@ class m {
369
520
  heightReference: n.HeightReference.CLAMP_TO_GROUND
370
521
  }
371
522
  });
523
+ this.finishedLabelEntities.push(o);
372
524
  }
373
525
  } else if (this.drawMode === "rectangle" && t.length >= 2) {
374
526
  const i = this.calculateRectangle(t[0], t[1]);
375
- e = this.entities.add({
527
+ this.offsetHeight > 0 ? e = this.entities.add({
528
+ name: "绘制的矩形",
529
+ rectangle: {
530
+ coordinates: i,
531
+ material: n.Color.GREEN.withAlpha(0.5),
532
+ heightReference: n.HeightReference.NONE,
533
+ extrudedHeight: this.offsetHeight
534
+ }
535
+ }) : e = this.entities.add({
376
536
  name: "绘制的矩形",
377
537
  rectangle: {
378
538
  coordinates: i,
@@ -380,16 +540,15 @@ class m {
380
540
  heightReference: n.HeightReference.CLAMP_TO_GROUND
381
541
  }
382
542
  });
383
- const r = this.calculateRectangleArea(i);
384
- if (r > 0) {
385
- const s = n.Rectangle.center(i);
386
- this.entities.add({
543
+ const s = this.calculateRectangleArea(i);
544
+ if (s > 0) {
545
+ const o = n.Rectangle.center(i), a = this.entities.add({
387
546
  position: n.Cartesian3.fromRadians(
388
- s.longitude,
389
- s.latitude
547
+ o.longitude,
548
+ o.latitude
390
549
  ),
391
550
  label: {
392
- text: `面积: ${r.toFixed(2)} km²`,
551
+ text: `面积: ${s.toFixed(2)} km²`,
393
552
  font: "14px sans-serif",
394
553
  fillColor: n.Color.WHITE,
395
554
  outlineColor: n.Color.BLACK,
@@ -399,9 +558,14 @@ class m {
399
558
  heightReference: n.HeightReference.CLAMP_TO_GROUND
400
559
  }
401
560
  });
561
+ this.finishedLabelEntities.push(a);
402
562
  }
403
563
  }
404
- e && this.finishedEntities.push(e), this.endDrawingInternal(!0), this.onDrawEndCallback && this.onDrawEndCallback(e);
564
+ e && this.finishedEntities.push(e), this.tempLabelEntities.forEach((i) => {
565
+ this.finishedLabelEntities.push(i);
566
+ }), this.tempLabelEntities = [], this.tempEntities.forEach((i) => {
567
+ i && i.point ? this.finishedPointEntities.push(i) : this.entities.remove(i);
568
+ }), this.tempEntities = [], this.tempPositions = [], this.drawMode = null, this.isDrawing = !1, this.deactivateDrawingHandlers(), this.onDrawEndCallback && this.onDrawEndCallback(e);
405
569
  }
406
570
  /**
407
571
  * 内部方法:重置绘图状态和清理临时数据
@@ -410,7 +574,9 @@ class m {
410
574
  endDrawingInternal(e) {
411
575
  this.tempEntities.forEach((t) => {
412
576
  this.entities.remove(t);
413
- }), this.tempEntities = [], this.tempPositions = [], e && (this.drawMode = null, this.isDrawing = !1, this.deactivateDrawingHandlers());
577
+ }), this.tempEntities = [], this.tempPositions = [], this.tempLabelEntities.forEach((t) => {
578
+ this.entities.remove(t);
579
+ }), this.tempLabelEntities = [], e && (this.drawMode = null, this.isDrawing = !1, this.deactivateDrawingHandlers());
414
580
  }
415
581
  /**
416
582
  * 公共方法:结束当前绘制(如果正在进行)
@@ -428,9 +594,40 @@ class m {
428
594
  * 清除所有已绘制的实体
429
595
  */
430
596
  clearAll() {
431
- this.endDrawing(), this.finishedEntities.forEach((e) => {
597
+ this.endDrawing(), this.clearAllPoints(), this.finishedEntities.forEach((e) => {
432
598
  this.entities.remove(e);
433
- }), this.finishedEntities = [];
599
+ }), this.finishedEntities = [], this.finishedLabelEntities.forEach((e) => {
600
+ e && this.entities.remove(e);
601
+ }), this.finishedLabelEntities = [], this.publicEntities.forEach((e) => {
602
+ e && this.entities.remove(e);
603
+ }), this.publicEntities = [], this.tempEntities.forEach((e) => {
604
+ e && this.entities.remove(e);
605
+ }), this.tempEntities = [], this.tempLabelEntities.forEach((e) => {
606
+ e && e.label && this.entities.remove(e);
607
+ }), this.tempLabelEntities = [], this.tempPositions = [];
608
+ }
609
+ /**
610
+ * 清除所有实体(包括未跟踪的实体)
611
+ * 这是一个更彻底的清理方法,会清除场景中的所有实体
612
+ */
613
+ clearAllEntities() {
614
+ this.endDrawing(), this.entities.removeAll(), this.finishedEntities = [], this.finishedLabelEntities = [], this.finishedPointEntities = [], this.publicEntities = [], this.tempEntities = [], this.tempLabelEntities = [], this.tempPositions = [];
615
+ }
616
+ /**
617
+ * 强制清除所有点实体
618
+ * 用于解决点实体无法删除的问题
619
+ */
620
+ clearAllPoints() {
621
+ this.finishedPointEntities.forEach((t) => {
622
+ t && this.entities.remove(t);
623
+ }), this.finishedPointEntities = [], this.tempEntities.forEach((t) => {
624
+ t && t.point && this.entities.remove(t);
625
+ });
626
+ const e = this.entities.values;
627
+ for (let t = e.length - 1; t >= 0; t--) {
628
+ const i = e[t];
629
+ i && i.point && this.entities.remove(i);
630
+ }
434
631
  }
435
632
  /**
436
633
  * 删除一个指定的已完成实体
@@ -449,39 +646,39 @@ class m {
449
646
  }
450
647
  // --- 辅助计算函数 ---
451
648
  calculateRectangle(e, t) {
452
- const i = n.Cartographic.fromCartesian(e), r = n.Cartographic.fromCartesian(t), s = Math.min(i.longitude, r.longitude), o = Math.max(i.longitude, r.longitude), a = Math.min(i.latitude, r.latitude), l = Math.max(i.latitude, r.latitude);
453
- return new n.Rectangle(s, a, o, l);
649
+ const i = n.Cartographic.fromCartesian(e), s = n.Cartographic.fromCartesian(t), o = Math.min(i.longitude, s.longitude), a = Math.max(i.longitude, s.longitude), r = Math.min(i.latitude, s.latitude), l = Math.max(i.latitude, s.latitude);
650
+ return new n.Rectangle(o, r, a, l);
454
651
  }
455
652
  calculateRectangleArea(e) {
456
- const t = e.west, i = e.south, r = e.east, s = e.north, o = n.Cartesian3.distance(
653
+ const t = e.west, i = e.south, s = e.east, o = e.north, a = n.Cartesian3.distance(
457
654
  n.Cartesian3.fromRadians(t, i),
458
- n.Cartesian3.fromRadians(r, i)
459
- ), a = n.Cartesian3.distance(
655
+ n.Cartesian3.fromRadians(s, i)
656
+ ), r = n.Cartesian3.distance(
460
657
  n.Cartesian3.fromRadians(t, i),
461
- n.Cartesian3.fromRadians(t, s)
658
+ n.Cartesian3.fromRadians(t, o)
462
659
  );
463
- return o * a / 1e6;
660
+ return a * r / 1e6;
464
661
  }
465
662
  calculatePolygonArea(e) {
466
663
  if (e.length < 3) return 0;
467
664
  const t = this.scene.globe.ellipsoid;
468
665
  let i = 0;
469
- const r = e.length;
470
- for (let s = 0; s < r; s++) {
471
- const o = t.cartesianToCartographic(e[s]), a = t.cartesianToCartographic(e[(s + 1) % r]);
472
- i += (a.longitude - o.longitude) * (2 + Math.sin(o.latitude) + Math.sin(a.latitude));
666
+ const s = e.length;
667
+ for (let o = 0; o < s; o++) {
668
+ const a = t.cartesianToCartographic(e[o]), r = t.cartesianToCartographic(e[(o + 1) % s]);
669
+ i += (r.longitude - a.longitude) * (2 + Math.sin(a.latitude) + Math.sin(r.latitude));
473
670
  }
474
671
  return i = Math.abs(i * 6378137 * 6378137 / 2), i / 1e6;
475
672
  }
476
673
  calculatePolygonCenter(e) {
477
674
  if (e.length === 0) return n.Cartesian3.ZERO;
478
- let t = 0, i = 0, r = 0;
479
- for (let s = 0; s < e.length; s++)
480
- t += e[s].x, i += e[s].y, r += e[s].z;
675
+ let t = 0, i = 0, s = 0;
676
+ for (let o = 0; o < e.length; o++)
677
+ t += e[o].x, i += e[o].y, s += e[o].z;
481
678
  return new n.Cartesian3(
482
679
  t / e.length,
483
680
  i / e.length,
484
- r / e.length
681
+ s / e.length
485
682
  );
486
683
  }
487
684
  // --- 回调注册 ---
@@ -514,21 +711,21 @@ class m {
514
711
  * @param radius 监控范围半径(米)
515
712
  * @param options 可选配置
516
713
  */
517
- drawMonitoringCircle(e, t, i, r, s) {
518
- const o = s?.borderColor || "#0062FF", a = s?.fillColor || "#0062FF", l = s?.borderWidth || 2, c = s?.name || "监控区域";
519
- return this.entities.add({
714
+ drawMonitoringCircle(e, t, i, s, o) {
715
+ const a = o?.borderColor || "#0062FF", r = o?.fillColor || "#0062FF", l = o?.borderWidth || 2, c = o?.name || "监控区域", h = this.entities.add({
520
716
  name: c,
521
717
  position: n.Cartesian3.fromDegrees(e, t, i),
522
718
  ellipse: {
523
- semiMajorAxis: r,
524
- semiMinorAxis: r,
525
- material: n.Color.fromCssColorString(a).withAlpha(0.27),
719
+ semiMajorAxis: s,
720
+ semiMinorAxis: s,
721
+ material: n.Color.fromCssColorString(r).withAlpha(0.27),
526
722
  outline: !0,
527
- outlineColor: n.Color.fromCssColorString(o),
723
+ outlineColor: n.Color.fromCssColorString(a),
528
724
  outlineWidth: l,
529
725
  heightReference: n.HeightReference.CLAMP_TO_GROUND
530
726
  }
531
727
  });
728
+ return this.publicEntities.push(h), h;
532
729
  }
533
730
  /**
534
731
  * 绘制垂直线条
@@ -537,21 +734,29 @@ class m {
537
734
  * @param height 高度
538
735
  * @param options 可选配置
539
736
  */
540
- drawVerticalLine(e, t, i, r) {
541
- const s = r?.color || "#0062FF", o = r?.width || 2;
542
- r?.dashPattern;
543
- const a = r?.name || "垂直线条", l = r?.groundHeight || 0, c = n.Cartesian3.fromDegrees(e, t, l), d = n.Cartesian3.fromDegrees(e, t, i);
544
- return this.entities.add({
545
- name: a,
737
+ drawVerticalLine(e, t, i, s) {
738
+ const o = s?.color || "#0062FF", a = s?.width || 2;
739
+ s?.dashPattern;
740
+ const r = s?.name || "垂直线条", l = s?.groundHeight || 0, c = n.Cartesian3.fromDegrees(
741
+ e,
742
+ t,
743
+ l
744
+ ), h = n.Cartesian3.fromDegrees(
745
+ e,
746
+ t,
747
+ i
748
+ ), d = this.entities.add({
749
+ name: r,
546
750
  polyline: {
547
- positions: [c, d],
548
- width: o,
751
+ positions: [c, h],
752
+ width: a,
549
753
  material: new n.PolylineDashMaterialProperty({
550
- color: n.Color.fromCssColorString(s)
754
+ color: n.Color.fromCssColorString(o)
551
755
  }),
552
756
  clampToGround: !1
553
757
  }
554
758
  });
759
+ return this.publicEntities.push(d), d;
555
760
  }
556
761
  /**
557
762
  * 销毁工具,清理所有事件监听器
@@ -624,7 +829,7 @@ class v {
624
829
  })
625
830
  }
626
831
  ];
627
- constructor(e, t, i = {}, r, s) {
832
+ constructor(e, t, i = {}, s, o) {
628
833
  this.viewer = e, this.container = t, this.config = {
629
834
  position: "bottom-right",
630
835
  buttonSize: 40,
@@ -635,7 +840,7 @@ class v {
635
840
  boxShadow: "0 2px 10px rgba(0, 0, 0, 0.1)",
636
841
  zIndex: 1e3,
637
842
  ...i
638
- }, this.searchCallback = r?.search, this.measurementCallback = r?.measurement, this.zoomCallback = r?.zoom, this.initialCenter = s, this.drawHelper = new m(e), this.setupDrawHelperCallbacks(), this.createToolbar();
843
+ }, this.searchCallback = s?.search, this.measurementCallback = s?.measurement, this.zoomCallback = s?.zoom, this.initialCenter = o, this.drawHelper = new m(e), this.setupDrawHelperCallbacks(), this.createToolbar();
639
844
  }
640
845
  /**
641
846
  * 设置初始中心点
@@ -660,7 +865,7 @@ class v {
660
865
  */
661
866
  updateButtonConfig(e, t) {
662
867
  const i = this.toolbarElement.querySelector(`[data-tool="${e}"]`);
663
- i && (t.title && (i.title = t.title), t.icon && this.setButtonIcon(i, t.icon), t.size && (i.style.width = `${t.size}px`, i.style.height = `${t.size}px`), t.color && (i.style.background = t.color));
868
+ i && (t.title && (i.title = t.title), t.icon && this.setButtonIcon(i, t.icon), t.size && (i.style.width = `${t.size}px`, i.style.height = `${t.size}px`), t.color && (i.style.color = t.color), t.backgroundColor && (i.style.background = t.backgroundColor), t.borderColor && (i.style.borderColor = t.borderColor), t.borderWidth && (i.style.borderWidth = t.borderWidth + "px"), t.borderStyle && (i.style.borderStyle = t.borderStyle), t.padding && (i.style.padding = t.padding), t.activeIcon && this.setButtonIcon(i, t.activeIcon));
664
869
  }
665
870
  /**
666
871
  * 添加自定义按钮
@@ -673,7 +878,8 @@ class v {
673
878
  size: e.size,
674
879
  color: e.color,
675
880
  hoverColor: e.hoverColor,
676
- activeColor: e.activeColor
881
+ activeColor: e.activeColor,
882
+ backgroundColor: e.backgroundColor
677
883
  }, i = this.createButton(t);
678
884
  this.toolbarElement.appendChild(i), this.config.buttons || (this.config.buttons = []), this.config.buttons.push(e);
679
885
  }
@@ -702,8 +908,8 @@ class v {
702
908
  const t = e.polyline.positions?.getValue(n.JulianDate.now());
703
909
  if (t && this.measurementCallback?.onDistanceComplete) {
704
910
  let i = 0;
705
- for (let r = 1; r < t.length; r++)
706
- i += n.Cartesian3.distance(t[r - 1], t[r]);
911
+ for (let s = 1; s < t.length; s++)
912
+ i += n.Cartesian3.distance(t[s - 1], t[s]);
707
913
  this.measurementCallback.onDistanceComplete(t, i);
708
914
  }
709
915
  } else if (e.polygon) {
@@ -725,10 +931,10 @@ class v {
725
931
  if (e.length < 3) return 0;
726
932
  const t = this.viewer.scene.globe.ellipsoid;
727
933
  let i = 0;
728
- const r = e.length;
729
- for (let s = 0; s < r; s++) {
730
- const o = t.cartesianToCartographic(e[s]), a = t.cartesianToCartographic(e[(s + 1) % r]);
731
- i += (a.longitude - o.longitude) * (2 + Math.sin(o.latitude) + Math.sin(a.latitude));
934
+ const s = e.length;
935
+ for (let o = 0; o < s; o++) {
936
+ const a = t.cartesianToCartographic(e[o]), r = t.cartesianToCartographic(e[(o + 1) % s]);
937
+ i += (r.longitude - a.longitude) * (2 + Math.sin(a.latitude) + Math.sin(r.latitude));
732
938
  }
733
939
  return i = Math.abs(i * 6378137 * 6378137 / 2), i / 1e6;
734
940
  }
@@ -767,16 +973,21 @@ class v {
767
973
  { id: "zoom-in", icon: "🔍+", title: "放大" },
768
974
  { id: "zoom-out", icon: "🔍-", title: "缩小" },
769
975
  { id: "fullscreen", icon: "⛶", title: "全屏" }
770
- ];
771
- return this.config.buttons && this.config.buttons.length > 0 ? this.config.buttons.map((t) => ({
772
- id: t.id,
773
- icon: typeof t.icon == "string" ? t.icon : "",
774
- title: t.title,
775
- size: t.size,
776
- color: t.color,
777
- hoverColor: t.hoverColor,
778
- activeColor: t.activeColor
779
- })) : e;
976
+ ], t = (i) => e.find((s) => s.id === i);
977
+ return this.config.buttons && this.config.buttons.length > 0 ? this.config.buttons.map((i) => {
978
+ const s = t(i.id);
979
+ return {
980
+ id: i.id || s?.id || "",
981
+ icon: typeof i.icon == "string" ? i.icon : s?.icon || "",
982
+ title: i.title || s?.title || "",
983
+ size: typeof i.size == "number" ? i.size : typeof s?.size == "number" ? s.size : void 0,
984
+ backgroundColor: i.backgroundColor || s?.backgroundColor || "",
985
+ borderColor: i.borderColor || s?.borderColor || "",
986
+ borderWidth: i.borderWidth || s?.borderWidth || 1,
987
+ borderStyle: i.borderStyle || s?.borderStyle || "solid",
988
+ color: i.color || s?.color || "rgba(66, 133, 244, 0.4)"
989
+ };
990
+ }) : e;
780
991
  }
781
992
  /**
782
993
  * 创建按钮
@@ -784,48 +995,86 @@ class v {
784
995
  createButton(e) {
785
996
  const t = document.createElement("div");
786
997
  t.className = "cesium-toolbar-button", t.setAttribute("data-tool", e.id), t.title = e.title;
787
- const i = e.size || this.config.buttonSize, r = e.color || "rgba(66, 133, 244, 0.4)", s = e.hoverColor || "rgba(51, 103, 214, 0.9)";
998
+ const i = e.size || this.config.buttonSize, s = e.color || "rgba(66, 133, 244, 0.4)", o = e.backgroundColor || "rgba(66, 133, 244, 0.4)", a = e.borderColor || "rgba(66, 133, 244, 0.4)", r = e.borderWidth || 1, l = e.borderStyle || "solid";
788
999
  return t.style.cssText = `
789
1000
  width: ${i}px;
790
1001
  height: ${i}px;
791
1002
  display: flex;
792
1003
  align-items: center;
793
1004
  justify-content: center;
794
- background: ${r};
795
- color: white;
796
- border: none;
797
- border-radius: 4px;
1005
+ background: ${o};
1006
+ color: ${s};
1007
+ border-width: ${r}px;
1008
+ border-style: ${l};
1009
+ border-color: ${a};
798
1010
  cursor: pointer;
799
- font-size: 14px;
800
1011
  font-weight: bold;
801
1012
  transition: all 0.2s ease;
802
1013
  user-select: none;
803
1014
  position: relative;
804
1015
  `, this.setButtonIcon(t, e.icon), t.addEventListener("mouseenter", () => {
805
- t.style.background = s, t.style.transform = "scale(1.05)";
1016
+ t.style.transform = "scale(1.05)";
806
1017
  }), t.addEventListener("mouseleave", () => {
807
- t.style.background = r, t.style.transform = "scale(1)";
1018
+ t.style.transform = "scale(1)";
808
1019
  }), this.setupButtonEvents(t, e), t;
809
1020
  }
810
1021
  /**
811
1022
  * 设置按钮图标
812
1023
  */
813
1024
  setButtonIcon(e, t) {
814
- typeof t == "string" ? e.innerHTML = t : t instanceof HTMLElement && (e.innerHTML = "", e.appendChild(t));
1025
+ t instanceof HTMLElement ? (e.innerHTML = "", e.appendChild(t)) : typeof t == "string" && (this.isImagePath(t) ? this.loadImageIcon(e, t) : e.innerHTML = t);
1026
+ }
1027
+ /**
1028
+ * 判断是否为图片路径
1029
+ */
1030
+ isImagePath(e) {
1031
+ return /\.(jpg|jpeg|png|gif|bmp|webp|svg|ico)$/i.test(e);
1032
+ }
1033
+ /**
1034
+ * 加载图片图标
1035
+ */
1036
+ loadImageIcon(e, t) {
1037
+ const i = new Image(), s = e.getBoundingClientRect(), o = window.getComputedStyle(e), a = s.width || parseInt(o.width) || 36, r = s.height || parseInt(o.height) || 36, l = Math.min(a, r) * 0.6, c = Math.min(a, r) * 0.6;
1038
+ i.width = l, i.height = c, i.onload = () => {
1039
+ e.appendChild(i);
1040
+ }, i.onerror = () => {
1041
+ console.warn(`Failed to load icon: ${t}`), this.setDefaultIcon(e, t);
1042
+ }, i.src = t;
1043
+ }
1044
+ /**
1045
+ * 设置默认图标(当图片加载失败时)
1046
+ */
1047
+ setDefaultIcon(e, t) {
1048
+ const i = t.split("/").pop()?.split(".")[0] || "icon";
1049
+ e.style.backgroundImage = "none", e.style.backgroundColor = "#ccc", e.style.position = "relative";
1050
+ const s = document.createElement("div");
1051
+ s.style.cssText = `
1052
+ position: absolute;
1053
+ top: 50%;
1054
+ left: 50%;
1055
+ transform: translate(-50%, -50%);
1056
+ font-size: 12px;
1057
+ color: #666;
1058
+ font-weight: bold;
1059
+ text-align: center;
1060
+ line-height: 1;
1061
+ `, s.textContent = i.charAt(0).toUpperCase(), e.innerHTML = "", e.appendChild(s);
815
1062
  }
816
1063
  /**
817
1064
  * 设置按钮事件
818
1065
  */
819
1066
  setupButtonEvents(e, t) {
820
- const i = this.config.buttons?.find((r) => r.id === t.id);
821
- i?.onClick ? e.addEventListener("click", (r) => {
822
- r.stopPropagation(), i.onClick(t.id, e);
823
- }) : ["search", "measure", "layers"].includes(t.id) ? (e.addEventListener("mouseenter", () => {
1067
+ const i = this.config.buttons?.find((s) => s.id === t.id);
1068
+ i?.onClick ? e.addEventListener("click", (s) => {
1069
+ s.stopPropagation(), i.onClick(t.id, e);
1070
+ }) : ["search", "measure", "layers"].includes(t.id) ? t.id === "search" ? e.addEventListener("click", (s) => {
1071
+ s.stopPropagation(), this.handleButtonClick(t.id, e);
1072
+ }) : (e.addEventListener("mouseenter", () => {
824
1073
  this.handleButtonClick(t.id, e);
825
1074
  }), e.addEventListener("mouseleave", () => {
826
1075
  this.closeMenuOnButtonLeave(t.id);
827
- })) : e.addEventListener("click", (r) => {
828
- r.stopPropagation(), this.handleButtonClick(t.id, e);
1076
+ })) : e.addEventListener("click", (s) => {
1077
+ s.stopPropagation(), this.handleButtonClick(t.id, e);
829
1078
  });
830
1079
  }
831
1080
  /**
@@ -834,17 +1083,13 @@ class v {
834
1083
  closeMenuOnButtonLeave(e) {
835
1084
  setTimeout(() => {
836
1085
  switch (e) {
837
- case "search":
838
- const t = this.toolbarElement.querySelector(".search-container");
839
- t && !t.matches(":hover") && t.remove();
840
- break;
841
1086
  case "measure":
842
- const i = this.toolbarElement.querySelector(".measurement-menu");
843
- i && !i.matches(":hover") && i.remove();
1087
+ const t = this.toolbarElement.querySelector(".measurement-menu");
1088
+ t && !t.matches(":hover") && t.remove();
844
1089
  break;
845
1090
  case "layers":
846
- const r = this.toolbarElement.querySelector(".layers-menu");
847
- r && !r.matches(":hover") && r.remove();
1091
+ const i = this.toolbarElement.querySelector(".layers-menu");
1092
+ i && !i.matches(":hover") && i.remove();
848
1093
  break;
849
1094
  }
850
1095
  }, 100);
@@ -884,8 +1129,11 @@ class v {
884
1129
  * 切换搜索功能
885
1130
  */
886
1131
  toggleSearch(e) {
887
- if (this.toolbarElement.querySelector(".search-container"))
1132
+ const t = this.toolbarElement.querySelector(".search-container");
1133
+ if (t) {
1134
+ t.remove();
888
1135
  return;
1136
+ }
889
1137
  const i = document.createElement("div");
890
1138
  i.className = "search-container", i.style.cssText = `
891
1139
  position: absolute;
@@ -900,48 +1148,52 @@ class v {
900
1148
  min-width: 200px;
901
1149
  z-index: 1001;
902
1150
  `;
903
- const r = document.createElement("input");
904
- r.type = "text", r.placeholder = "请输入地址", r.style.cssText = `
1151
+ const s = document.createElement("input");
1152
+ s.type = "text", s.placeholder = "请输入地址", s.style.cssText = `
905
1153
  padding: 6px 8px;
906
1154
  border: 1px solid #ddd;
907
1155
  border-radius: 3px;
908
1156
  font-size: 14px;
909
1157
  outline: none;
910
1158
  `;
911
- const s = document.createElement("div");
912
- s.className = "search-results", s.style.cssText = `
1159
+ const o = document.createElement("div");
1160
+ o.className = "search-results", o.style.cssText = `
913
1161
  margin-top: 8px;
914
1162
  max-height: 200px;
915
1163
  overflow-y: auto;
916
- `, i.appendChild(r), i.appendChild(s), this.toolbarElement.insertBefore(i, e);
917
- let o;
918
- r.addEventListener("input", () => {
919
- clearTimeout(o);
920
- const l = r.value.trim();
1164
+ `, i.appendChild(s), i.appendChild(o), this.toolbarElement.insertBefore(i, e);
1165
+ let a;
1166
+ s.addEventListener("input", () => {
1167
+ clearTimeout(a);
1168
+ const c = s.value.trim();
921
1169
  if (this.searchCallback?.onSearchInput) {
922
- this.searchCallback.onSearchInput(l, s);
1170
+ this.searchCallback.onSearchInput(c, o);
923
1171
  return;
924
1172
  }
925
- if (l.length < 2) {
926
- s.innerHTML = "";
1173
+ if (c.length < 2) {
1174
+ o.innerHTML = "";
927
1175
  return;
928
1176
  }
929
- o = setTimeout(async () => {
1177
+ a = setTimeout(async () => {
930
1178
  if (this.searchCallback?.onSearch)
931
1179
  try {
932
- const c = await this.searchCallback.onSearch(l);
933
- this.displaySearchResults(c, s);
934
- } catch (c) {
935
- console.error("搜索失败:", c), s.innerHTML = '<div style="padding: 8px; color: #666;">搜索失败</div>';
1180
+ const h = await this.searchCallback.onSearch(c);
1181
+ this.displaySearchResults(h, o);
1182
+ } catch (h) {
1183
+ console.error("搜索失败:", h), o.innerHTML = '<div style="padding: 8px; color: #666;">搜索失败</div>';
936
1184
  }
937
1185
  else
938
- this.performDefaultSearch(l, s);
1186
+ this.performDefaultSearch(c, o);
939
1187
  }, 300);
940
1188
  });
941
- const a = () => {
942
- i.remove();
1189
+ const r = (c) => {
1190
+ !i.contains(c.target) && !e.contains(c.target) && (i.remove(), document.removeEventListener("click", r), document.removeEventListener("keydown", l));
1191
+ }, l = (c) => {
1192
+ c.key === "Escape" && (i.remove(), document.removeEventListener("click", r), document.removeEventListener("keydown", l));
943
1193
  };
944
- i.addEventListener("mouseleave", a);
1194
+ setTimeout(() => {
1195
+ document.addEventListener("click", r), document.addEventListener("keydown", l), s.focus();
1196
+ }, 100);
945
1197
  }
946
1198
  /**
947
1199
  * 显示搜索结果
@@ -956,22 +1208,22 @@ class v {
956
1208
  return;
957
1209
  }
958
1210
  e.forEach((i) => {
959
- const r = document.createElement("div");
960
- r.style.cssText = `
1211
+ const s = document.createElement("div");
1212
+ s.style.cssText = `
961
1213
  padding: 8px;
962
1214
  border-bottom: 1px solid #f0f0f0;
963
1215
  cursor: pointer;
964
1216
  transition: background-color 0.2s;
965
- `, r.innerHTML = `
1217
+ `, s.innerHTML = `
966
1218
  <div style="font-weight: bold; margin-bottom: 2px;">${i.name}</div>
967
1219
  <div style="font-size: 12px; color: #666;">${i.address}</div>
968
- `, r.addEventListener("mouseenter", () => {
969
- r.style.backgroundColor = "#f5f5f5";
970
- }), r.addEventListener("mouseleave", () => {
971
- r.style.backgroundColor = "transparent";
972
- }), r.addEventListener("click", () => {
1220
+ `, s.addEventListener("mouseenter", () => {
1221
+ s.style.backgroundColor = "#f5f5f5";
1222
+ }), s.addEventListener("mouseleave", () => {
1223
+ s.style.backgroundColor = "transparent";
1224
+ }), s.addEventListener("click", () => {
973
1225
  this.selectSearchResult(i), t.parentElement?.remove();
974
- }), t.appendChild(r);
1226
+ }), t.appendChild(s);
975
1227
  });
976
1228
  }
977
1229
  /**
@@ -1039,27 +1291,27 @@ class v {
1039
1291
  { id: "measure-area", text: "测面积", icon: "📐" },
1040
1292
  { id: "measure-distance", text: "测距", icon: "📏" },
1041
1293
  { id: "clear-measurement", text: "清除", icon: "🗑️" }
1042
- ].forEach((o) => {
1043
- const a = document.createElement("div");
1044
- a.style.cssText = `
1294
+ ].forEach((a) => {
1295
+ const r = document.createElement("div");
1296
+ r.style.cssText = `
1045
1297
  padding: 8px 12px;
1046
1298
  cursor: pointer;
1047
1299
  display: flex;
1048
1300
  align-items: center;
1049
1301
  gap: 8px;
1050
1302
  transition: background-color 0.2s;
1051
- `, a.innerHTML = `${o.icon} ${o.text}`, a.addEventListener("mouseenter", () => {
1052
- a.style.backgroundColor = "#f5f5f5";
1053
- }), a.addEventListener("mouseleave", () => {
1054
- a.style.backgroundColor = "transparent";
1055
- }), a.addEventListener("click", () => {
1056
- this.handleMeasurementAction(o.id), i.remove();
1057
- }), i.appendChild(a);
1303
+ `, r.innerHTML = `${a.icon} ${a.text}`, r.addEventListener("mouseenter", () => {
1304
+ r.style.backgroundColor = "#f5f5f5";
1305
+ }), r.addEventListener("mouseleave", () => {
1306
+ r.style.backgroundColor = "transparent";
1307
+ }), r.addEventListener("click", () => {
1308
+ this.handleMeasurementAction(a.id), i.remove();
1309
+ }), i.appendChild(r);
1058
1310
  }), this.toolbarElement.insertBefore(i, e);
1059
- const s = () => {
1311
+ const o = () => {
1060
1312
  i.remove();
1061
1313
  };
1062
- i.addEventListener("mouseleave", s);
1314
+ i.addEventListener("mouseleave", o);
1063
1315
  }
1064
1316
  /**
1065
1317
  * 处理测量操作
@@ -1107,14 +1359,14 @@ class v {
1107
1359
  display: flex;
1108
1360
  flex-direction: column;
1109
1361
  `;
1110
- const r = document.createElement("div");
1111
- r.style.cssText = `
1362
+ const s = document.createElement("div");
1363
+ s.style.cssText = `
1112
1364
  display: flex;
1113
1365
  flex-direction: column;
1114
1366
  gap: 4px;
1115
- `, r.innerHTML = '<div style="font-weight: bold; margin-bottom: 8px; color: #333; font-size: 14px;">地图类型</div>', this.mapTypes.forEach((o) => {
1116
- const a = document.createElement("div");
1117
- a.style.cssText = `
1367
+ `, s.innerHTML = '<div style="font-weight: bold; margin-bottom: 8px; color: #333; font-size: 14px;">地图类型</div>', this.mapTypes.forEach((a) => {
1368
+ const r = document.createElement("div");
1369
+ r.style.cssText = `
1118
1370
  display: flex;
1119
1371
  align-items: center;
1120
1372
  gap: 8px;
@@ -1124,39 +1376,39 @@ class v {
1124
1376
  transition: background-color 0.2s;
1125
1377
  width: 100%;
1126
1378
  box-sizing: border-box;
1127
- ${o.id === this.currentMapType ? "background-color: #e3f2fd;" : ""}
1379
+ ${a.id === this.currentMapType ? "background-color: #e3f2fd;" : ""}
1128
1380
  `;
1129
1381
  const l = document.createElement("img");
1130
- l.src = o.thumbnail, l.style.cssText = `
1382
+ l.src = a.thumbnail, l.style.cssText = `
1131
1383
  width: 24px;
1132
1384
  height: 24px;
1133
1385
  border-radius: 3px;
1134
1386
  flex-shrink: 0;
1135
1387
  `;
1136
1388
  const c = document.createElement("span");
1137
- c.textContent = o.name, c.style.cssText = `
1389
+ c.textContent = a.name, c.style.cssText = `
1138
1390
  font-size: 14px;
1139
1391
  color: #333;
1140
1392
  flex: 1;
1141
1393
  `;
1142
- const d = document.createElement("span");
1143
- o.id === this.currentMapType && (d.textContent = "✓", d.style.cssText = `
1394
+ const h = document.createElement("span");
1395
+ a.id === this.currentMapType && (h.textContent = "✓", h.style.cssText = `
1144
1396
  color: #1976d2;
1145
1397
  font-weight: bold;
1146
1398
  font-size: 16px;
1147
1399
  flex-shrink: 0;
1148
- `), a.appendChild(l), a.appendChild(c), a.appendChild(d), a.addEventListener("mouseenter", () => {
1149
- o.id !== this.currentMapType && (a.style.backgroundColor = "#f5f5f5");
1150
- }), a.addEventListener("mouseleave", () => {
1151
- o.id !== this.currentMapType && (a.style.backgroundColor = "transparent");
1152
- }), a.addEventListener("click", () => {
1153
- this.switchMapType(o.id), i.remove();
1154
- }), r.appendChild(a);
1155
- }), i.appendChild(r), this.toolbarElement.insertBefore(i, e);
1156
- const s = () => {
1400
+ `), r.appendChild(l), r.appendChild(c), r.appendChild(h), r.addEventListener("mouseenter", () => {
1401
+ a.id !== this.currentMapType && (r.style.backgroundColor = "#f5f5f5");
1402
+ }), r.addEventListener("mouseleave", () => {
1403
+ a.id !== this.currentMapType && (r.style.backgroundColor = "transparent");
1404
+ }), r.addEventListener("click", () => {
1405
+ this.switchMapType(a.id), i.remove();
1406
+ }), s.appendChild(r);
1407
+ }), i.appendChild(s), this.toolbarElement.insertBefore(i, e);
1408
+ const o = () => {
1157
1409
  i.remove();
1158
1410
  };
1159
- i.addEventListener("mouseleave", s);
1411
+ i.addEventListener("mouseleave", o);
1160
1412
  }
1161
1413
  /**
1162
1414
  * 切换地图类型
@@ -1230,7 +1482,7 @@ class v {
1230
1482
  this.toolbarElement && this.toolbarElement.parentNode && this.toolbarElement.parentNode.removeChild(this.toolbarElement), this.drawHelper.destroy();
1231
1483
  }
1232
1484
  }
1233
- function x() {
1485
+ function y() {
1234
1486
  return new n.UrlTemplateImageryProvider({
1235
1487
  url: "https://webst0{s}.is.autonavi.com/appmaptile?style=7&x={x}&y={y}&z={z}",
1236
1488
  subdomains: ["1", "2", "3", "4"],
@@ -1240,15 +1492,15 @@ function x() {
1240
1492
  credit: "© 高德地图"
1241
1493
  });
1242
1494
  }
1243
- async function y(h, e, t = { longitude: 120.2052342, latitude: 30.2489634, height: 1e3, pitch: -60, heading: 0 }) {
1495
+ async function x(u, e, t = { longitude: 120.2052342, latitude: 30.2489634, height: 1e3, pitch: -60, heading: 0 }) {
1244
1496
  E.defaultAccessToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI3M2M3NWU1Ni0xZmJkLTRkNjAtOTk4NC0wZDZhNWFiOWJlZDEiLCJpZCI6MzMxNTg1LCJpYXQiOjE3NTUyMjQ2MzB9.WBUG7ctHKtOrnay1ng8JNfaNgngbkNgOmRXP59OJ7ME";
1245
- const i = new b(h, {
1497
+ const i = new b(u, {
1246
1498
  timeline: !1,
1247
1499
  animation: !1,
1248
1500
  baseLayerPicker: !1,
1249
1501
  ...e
1250
1502
  });
1251
- return !e.terrainProvider && !e.terrain && (i.terrainProvider = await w()), e.mapType === "gaode" && (i.imageryLayers.removeAll(), i.imageryLayers.addImageryProvider(x())), t && i.camera.flyTo({
1503
+ return !e.terrainProvider && !e.terrain && (i.terrainProvider = await w()), e.mapType === "gaode" && (i.imageryLayers.removeAll(), i.imageryLayers.addImageryProvider(y())), t && i.camera.flyTo({
1252
1504
  destination: n.Cartesian3.fromDegrees(t.longitude, t.latitude, t.height),
1253
1505
  // 中国中心坐标
1254
1506
  orientation: {
@@ -1262,12 +1514,12 @@ async function y(h, e, t = { longitude: 120.2052342, latitude: 30.2489634, heigh
1262
1514
  const L = {
1263
1515
  CesiumMapToolbar: v,
1264
1516
  DrawHelper: m,
1265
- initCesium: y
1517
+ initCesium: x
1266
1518
  };
1267
1519
  export {
1268
1520
  v as CesiumMapToolbar,
1269
1521
  m as DrawHelper,
1270
1522
  L as default,
1271
- y as initCesium
1523
+ x as initCesium
1272
1524
  };
1273
1525
  //# sourceMappingURL=index.es.js.map