@sword916/vae-map-plus 1.0.0

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.
Files changed (86) hide show
  1. package/README.md +3 -0
  2. package/build/index.mjs +113 -0
  3. package/examples/App.vue +18 -0
  4. package/examples/index.js +13 -0
  5. package/examples/router/index.js +35 -0
  6. package/examples/views/amap.vue +29 -0
  7. package/examples/views/amarker.vue +58 -0
  8. package/examples/views/buffer.vue +66 -0
  9. package/examples/views/cluster.vue +74 -0
  10. package/examples/views/cover.vue +85 -0
  11. package/examples/views/draw-line.vue +49 -0
  12. package/examples/views/draw.vue +54 -0
  13. package/examples/views/echarts.vue +142 -0
  14. package/examples/views/emarker.vue +39 -0
  15. package/examples/views/image.vue +182 -0
  16. package/examples/views/index.vue +61 -0
  17. package/examples/views/lrmap.vue +108 -0
  18. package/examples/views/map.vue +82 -0
  19. package/examples/views/measure.vue +86 -0
  20. package/examples/views/parts/popup.vue +39 -0
  21. package/examples/views/parts/tooltip.vue +39 -0
  22. package/examples/views/push-area.vue +52 -0
  23. package/examples/views/push-line.vue +84 -0
  24. package/examples/views/trace.vue +49 -0
  25. package/index.html +13 -0
  26. package/jsconfig.json +17 -0
  27. package/package.json +47 -0
  28. package/public/favicon.ico +0 -0
  29. package/public/images/game.png +0 -0
  30. package/public/images/grid.png +0 -0
  31. package/public/images/marker.png +0 -0
  32. package/public/index.html +30 -0
  33. package/src/components/resize-listener/component.jsx +30 -0
  34. package/src/components/resize-listener/index.js +3 -0
  35. package/src/composables/useAutoMessage.js +41 -0
  36. package/src/composables/useContextMenu.js +99 -0
  37. package/src/composables/useMapMeasure.js +191 -0
  38. package/src/composables/useResizeObserver.js +81 -0
  39. package/src/mixins/message.js +1 -0
  40. package/src/packages/index.js +16 -0
  41. package/src/packages/vae-amap/index.js +8 -0
  42. package/src/packages/vae-amap/style.less +9 -0
  43. package/src/packages/vae-amap/vae-amap.jsx +98 -0
  44. package/src/packages/vae-cloudmap/ctrl-context-menu/index.vue +74 -0
  45. package/src/packages/vae-cloudmap/ctrl-draw/index.vue +499 -0
  46. package/src/packages/vae-cloudmap/ctrl-draw-line/index.vue +161 -0
  47. package/src/packages/vae-cloudmap/index.js +57 -0
  48. package/src/packages/vae-cloudmap/scripts/L.MarkerCluster/index.js +2690 -0
  49. package/src/packages/vae-cloudmap/scripts/L.MarkerCluster/style.css +14 -0
  50. package/src/packages/vae-cloudmap/scripts/L.Vae.CRS/index.js +212 -0
  51. package/src/packages/vae-cloudmap/scripts/L.Vae.Client/index.js +780 -0
  52. package/src/packages/vae-cloudmap/scripts/Mixin.ContextMenu/index.js +101 -0
  53. package/src/packages/vae-cloudmap/style.less +163 -0
  54. package/src/packages/vae-cloudmap/vae-cloudmap.jsx +272 -0
  55. package/src/packages/vae-map/ctrl-context-menu/index.vue +74 -0
  56. package/src/packages/vae-map/ctrl-draw/index.vue +498 -0
  57. package/src/packages/vae-map/ctrl-draw-line/index.vue +128 -0
  58. package/src/packages/vae-map/index.js +59 -0
  59. package/src/packages/vae-map/scripts/L.MarkerCluster/index.js +2690 -0
  60. package/src/packages/vae-map/scripts/L.MarkerCluster/style.css +14 -0
  61. package/src/packages/vae-map/scripts/L.Vae.CRS/index.js +114 -0
  62. package/src/packages/vae-map/scripts/L.Vae.Client/index.js +548 -0
  63. package/src/packages/vae-map/scripts/Mixin.ContextMenu/index.js +1 -0
  64. package/src/packages/vae-map/style.less +161 -0
  65. package/src/packages/vae-map/vae-lrmap.jsx +237 -0
  66. package/src/packages/vae-map/vae-map.jsx +135 -0
  67. package/src/plugins/L.AnimatedMarker/index.js +158 -0
  68. package/src/plugins/L.EchartsLayer/index.js +339 -0
  69. package/src/plugins/L.ElasticMarker/index.js +162 -0
  70. package/src/plugins/L.FootageCalculator.Area/index.js +263 -0
  71. package/src/plugins/L.FootageCalculator.Line/index.js +273 -0
  72. package/src/plugins/L.GeoUtil/buffer.js +67 -0
  73. package/src/plugins/L.GeoUtil/index.js +284 -0
  74. package/src/plugins/L.Glyphicon/index.js +91 -0
  75. package/src/plugins/L.Glyphicon/style.less +37 -0
  76. package/src/plugins/L.MarkerClusterX/index.js +93 -0
  77. package/src/plugins/L.MarkerClusterX/style.less +162 -0
  78. package/src/plugins/L.SafeDivOverlay/index.js +55 -0
  79. package/src/plugins/L.TileLayer.ChinaProvider/index.js +108 -0
  80. package/src/plugins/L.VuePopup/index.js +67 -0
  81. package/src/plugins/L.VueTooltip/index.js +63 -0
  82. package/src/plugins/Mixin.Map.Measure/index.js +248 -0
  83. package/src/plugins/globals/index.js +7 -0
  84. package/src/utils/index.js +36 -0
  85. package/src/utils/resize-event.js +45 -0
  86. package/vite.config.mjs +25 -0
@@ -0,0 +1,498 @@
1
+ <template>
2
+ <div class="vae-map-ctrl--draw">
3
+ <div class="item-group">
4
+ <template v-if="showPolyFuncs">
5
+ <div class="item" title="绘制">
6
+ <div class="item-icon fas fa-pen-alt" :class="actionDisabled('draw')" @click="startDrawMode" />
7
+ <div v-if="drawStatus === 'draw'" class="tooltips">
8
+ <span @click="drawStatus = 'none'">取消</span>
9
+ <span @click="removeLastVertx">移除上一个节点</span>
10
+ </div>
11
+ </div>
12
+ <div class="item" title="编辑">
13
+ <div class="item-icon fas fa-draw-polygon" :class="actionDisabled('edit')" @click="startEditMode" />
14
+ <div v-if="drawStatus === 'edit'" class="tooltips">
15
+ <span @click="drawStatus = 'none'">完成</span>
16
+ </div>
17
+ </div>
18
+ <div class="item" title="移动">
19
+ <div class="item-icon fas fa-expand-arrows-alt" :class="actionDisabled('drag')" @click="startDragMode" />
20
+ <div v-if="drawStatus === 'drag'" class="tooltips">
21
+ <span @click="drawStatus = 'none'">完成</span>
22
+ </div>
23
+ </div>
24
+ </template>
25
+ <div class="item" title="机头机尾">
26
+ <div class="item-icon fas fa-map-pin" :class="actionDisabled('pick')" @click="startPickMode" />
27
+ <div v-if="drawStatus === 'pick'" class="tooltips">
28
+ <span @click="drawStatus = 'none'">取消</span>
29
+ <span @click="resetPickMode">重置</span>
30
+ <span v-if="htIndex === 5" @click="finishPick">完成</span>
31
+ </div>
32
+ </div>
33
+ <div v-if="showPolyFuncs" class="item" title="清除">
34
+ <div class="item-icon fas fa-trash-alt" @click="clearDrawItems" />
35
+ </div>
36
+ </div>
37
+ <div class="item-group">
38
+ <div class="item" title="保存">
39
+ <div class="item-icon fas fa-save" :class="actionDisabled('save')" @click="saveItems" />
40
+ </div>
41
+ </div>
42
+ </div>
43
+ </template>
44
+
45
+ <script setup>
46
+ import { computed, ref, watch } from 'vue'
47
+ import { ElMessage } from 'element-plus'
48
+
49
+ defineOptions({
50
+ name: 'VaeMapCtrlDraw'
51
+ })
52
+
53
+ const CMOptions = {
54
+ unpicked: { color: '#ffc107', fillColor: '#fff', fillOpacity: 1, radius: 6 },
55
+ picked: { color: '#28a745', fillColor: '#fff', fillOpacity: 1, radius: 7, weight: 5 },
56
+ hint: { color: 'transparent', radius: 1, weight: 1, interactive: false }
57
+ }
58
+
59
+ function TTContent({ action, content, style }) {
60
+ const textHtml = `<span class="${style ?? ''}">${content}</span>`
61
+ if (action) {
62
+ return `<span><span class="action">${action}</span>${textHtml}</span>`
63
+ }
64
+ return `<span>${textHtml}</span>`
65
+ }
66
+
67
+ function PickedMarker(sign, latLng) {
68
+ let config = { content: '-' }
69
+ switch (sign) {
70
+ case 'hs':
71
+ config = { content: '机头起点', style: 'green' }
72
+ break
73
+ case 'ts':
74
+ config = { content: '机尾起点', style: 'red' }
75
+ break
76
+ case 'he':
77
+ config = { content: '机头终点', style: 'green' }
78
+ break
79
+ case 'te':
80
+ config = { content: '机尾终点', style: 'red' }
81
+ break
82
+ }
83
+ return L.circleMarker(latLng, CMOptions.hint).bindTooltip(TTContent(config), {
84
+ direction: 'right',
85
+ permanent: true,
86
+ className: 'ht-tooltip'
87
+ })
88
+ }
89
+
90
+ function adjustIndex(index, length) {
91
+ if (index > length - 1) {
92
+ return index - length
93
+ }
94
+ if (index < 0) {
95
+ return index + length
96
+ }
97
+ return index
98
+ }
99
+
100
+ const props = defineProps({
101
+ htOnly: {
102
+ type: Boolean,
103
+ default: false
104
+ }
105
+ })
106
+
107
+ const emit = defineEmits(['on-create', 'on-save'])
108
+
109
+ const enabled = ref(false)
110
+ const mapInstance = ref(null)
111
+ const drawItems = L.layerGroup()
112
+ const drawStatus = ref('none')
113
+ const polygon = ref(null)
114
+ const htItems = L.layerGroup()
115
+ const htHelpItems = L.layerGroup()
116
+ const htHelpCacheItems = L.layerGroup()
117
+ const htTooltip = ref(null)
118
+ const htIndex = ref(0)
119
+ const hsIndex = ref(-1)
120
+ const tsIndex = ref(-1)
121
+ const heIndex = ref(-1)
122
+ const teIndex = ref(-1)
123
+ const htHelpMarkers = new Map()
124
+
125
+ const polygonReady = computed(() => polygon.value && polygon.value.getLatLngs()[0].length > 3)
126
+ const drawReady = computed(() => enabled.value && drawStatus.value !== 'finish')
127
+ const editReady = computed(() => enabled.value && polygonReady.value && drawStatus.value !== 'finish')
128
+ const dragReady = computed(() => enabled.value && polygonReady.value && drawStatus.value !== 'finish')
129
+ const pickReady = computed(() => enabled.value && polygonReady.value)
130
+ const saveReady = computed(() => enabled.value && ['finish', 'reset'].includes(drawStatus.value))
131
+ const showPolyFuncs = computed(() => !props.htOnly)
132
+
133
+ watch(drawStatus, (value) => {
134
+ if (value === 'draw') {
135
+ quitEditMode()
136
+ quitDragMode()
137
+ quitPickMode()
138
+ } else if (value === 'edit') {
139
+ quitDrawMode()
140
+ quitDragMode()
141
+ quitPickMode()
142
+ } else if (value === 'drag') {
143
+ quitDrawMode()
144
+ quitEditMode()
145
+ quitPickMode()
146
+ } else if (value === 'pick') {
147
+ quitDrawMode()
148
+ quitEditMode()
149
+ quitDragMode()
150
+ } else if (value === 'none' || value === 'reset') {
151
+ quitDrawMode()
152
+ quitEditMode()
153
+ quitDragMode()
154
+ quitPickMode()
155
+ } else if (value === 'finish') {
156
+ quitDrawMode()
157
+ quitEditMode()
158
+ quitDragMode()
159
+ }
160
+ })
161
+
162
+ const enable = (map, data) => {
163
+ if (!map) {
164
+ return
165
+ }
166
+
167
+ enabled.value = true
168
+ mapInstance.value = map
169
+ mapInstance.value.pm.setLang('zh')
170
+ drawItems.addTo(mapInstance.value)
171
+ mapInstance.value.on('pm:create', ({ shape, layer }) => {
172
+ layer.remove()
173
+ layer.addTo(drawItems)
174
+ if (shape === 'Polygon') {
175
+ if (layer.getLatLngs()[0].length === 3) {
176
+ layer.remove()
177
+ drawStatus.value = 'none'
178
+ ElMessage.error('绘制错误,请至少绘制 4 个边')
179
+ } else {
180
+ if (polygon.value) {
181
+ polygon.value.remove()
182
+ }
183
+ polygon.value = layer
184
+ drawStatus.value = 'none'
185
+ ElMessage.success('绘制完成')
186
+ emit('on-create', polygon.value)
187
+ }
188
+ }
189
+ })
190
+
191
+ const latLngs = data?.latLngs
192
+ const currentHtIndex = data?.htIndex
193
+ if (Array.isArray(latLngs) && latLngs.length > 3) {
194
+ polygon.value = L.polygon(latLngs).addTo(drawItems)
195
+ if (Array.isArray(currentHtIndex) && currentHtIndex.length === 4) {
196
+ if (!drawItems.hasLayer(htItems)) {
197
+ drawItems.addLayer(htItems)
198
+ }
199
+ hsIndex.value = currentHtIndex[0]
200
+ PickedMarker('hs', latLngs[hsIndex.value]).addTo(htItems)
201
+ tsIndex.value = currentHtIndex[1]
202
+ PickedMarker('ts', latLngs[tsIndex.value]).addTo(htItems)
203
+ heIndex.value = currentHtIndex[2]
204
+ PickedMarker('he', latLngs[heIndex.value]).addTo(htItems)
205
+ teIndex.value = currentHtIndex[3]
206
+ PickedMarker('te', latLngs[teIndex.value]).addTo(htItems)
207
+ drawStatus.value = 'finish'
208
+ }
209
+ emit('on-create', polygon.value)
210
+ }
211
+ }
212
+
213
+ const clearDrawItems = () => {
214
+ drawStatus.value = 'reset'
215
+ drawItems.clearLayers()
216
+ polygon.value = null
217
+ ElMessage.success('已清理')
218
+ }
219
+
220
+ const startDrawMode = () => {
221
+ if (drawReady.value) {
222
+ mapInstance.value.pm.enableDraw('Polygon')
223
+ drawStatus.value = 'draw'
224
+ }
225
+ }
226
+
227
+ const removeLastVertx = () => {
228
+ const target = mapInstance.value.pm.Draw.Polygon
229
+ target._removeLastVertex()
230
+ if (!target._enabled) {
231
+ drawStatus.value = 'none'
232
+ }
233
+ }
234
+
235
+ const quitDrawMode = () => {
236
+ mapInstance.value?.pm.disableDraw('Polygon')
237
+ }
238
+
239
+ const startEditMode = () => {
240
+ if (editReady.value && !polygon.value.pm.enabled()) {
241
+ polygon.value.pm.enable()
242
+ drawStatus.value = 'edit'
243
+ }
244
+ }
245
+
246
+ const quitEditMode = () => {
247
+ if (polygon.value?.pm.enabled()) {
248
+ polygon.value.pm.disable()
249
+ }
250
+ }
251
+
252
+ const startDragMode = () => {
253
+ if (dragReady.value && !mapInstance.value.pm.globalDragModeEnabled()) {
254
+ mapInstance.value.pm.toggleGlobalDragMode()
255
+ drawStatus.value = 'drag'
256
+ }
257
+ }
258
+
259
+ const quitDragMode = () => {
260
+ if (mapInstance.value?.pm.globalDragModeEnabled()) {
261
+ mapInstance.value.pm.toggleGlobalDragMode()
262
+ }
263
+ }
264
+
265
+ const handlePickMove = (event) => {
266
+ if (htTooltip.value) {
267
+ htTooltip.value.setLatLng(event.latlng)
268
+ if (!htHelpItems.hasLayer(htTooltip.value)) {
269
+ htTooltip.value.addTo(htHelpItems)
270
+ }
271
+ }
272
+ }
273
+
274
+ const resetPickMode = () => {
275
+ htItems.clearLayers()
276
+ htHelpItems.clearLayers()
277
+ htHelpCacheItems.clearLayers()
278
+ htHelpMarkers.clear()
279
+
280
+ const latLngs = polygon.value.getLatLngs()[0]
281
+ latLngs.forEach((latLng, index) => {
282
+ const marker = L.circleMarker(latLng, CMOptions.unpicked).addTo(htHelpItems)
283
+ bindPickEvent(marker, index)
284
+ htHelpMarkers.set(index, marker)
285
+ })
286
+
287
+ hsIndex.value = -1
288
+ tsIndex.value = -1
289
+ heIndex.value = -1
290
+ teIndex.value = -1
291
+ htIndex.value = 1
292
+
293
+ htTooltip.value = L.circleMarker(mapInstance.value.getCenter(), CMOptions.hint).bindTooltip(TTContent({
294
+ action: '请选择',
295
+ content: '机头起点',
296
+ style: 'green'
297
+ }), {
298
+ direction: 'bottom',
299
+ offset: [0, 8],
300
+ permanent: true,
301
+ className: 'ht-tooltip'
302
+ })
303
+ mapInstance.value.off('mousemove', handlePickMove)
304
+ mapInstance.value.on('mousemove', handlePickMove)
305
+ }
306
+
307
+ const startPickMode = () => {
308
+ if (pickReady.value) {
309
+ drawStatus.value = 'pick'
310
+ htItems.addTo(drawItems)
311
+ htHelpItems.addTo(drawItems)
312
+ resetPickMode()
313
+ }
314
+ }
315
+
316
+ const quitPickMode = () => {
317
+ mapInstance.value?.off('mousemove', handlePickMove)
318
+ if (drawStatus.value !== 'finish') {
319
+ htItems.clearLayers()
320
+ hsIndex.value = -1
321
+ tsIndex.value = -1
322
+ heIndex.value = -1
323
+ teIndex.value = -1
324
+ }
325
+ htTooltip.value = null
326
+ htHelpItems.clearLayers()
327
+ htHelpCacheItems.clearLayers()
328
+ htHelpMarkers.clear()
329
+ htIndex.value = 0
330
+ }
331
+
332
+ const finishPick = () => {
333
+ if (htIndex.value === 5) {
334
+ drawStatus.value = 'finish'
335
+ quitPickMode()
336
+ ElMessage.success('标注完成')
337
+ } else {
338
+ drawStatus.value = 'none'
339
+ }
340
+ }
341
+
342
+ const doPickMarker = (index) => {
343
+ let sign
344
+ let next
345
+ if (htIndex.value === 1) {
346
+ sign = 'hs'
347
+ next = { action: '请选择', content: '机尾起点', style: 'red' }
348
+ } else if (htIndex.value === 2) {
349
+ sign = 'ts'
350
+ next = { action: '请选择', content: '机头终点', style: 'green' }
351
+ } else if (htIndex.value === 3) {
352
+ sign = 'he'
353
+ next = { action: '请选择', content: '机尾终点', style: 'red' }
354
+ } else {
355
+ sign = 'te'
356
+ next = { content: '-' }
357
+ }
358
+
359
+ const target = htHelpMarkers.get(index)
360
+ const indexRefs = { hs: hsIndex, ts: tsIndex, he: heIndex, te: teIndex }
361
+ PickedMarker(sign, target.getLatLng()).addTo(htItems)
362
+ target.off('click')
363
+ target.remove()
364
+ htHelpMarkers.delete(index)
365
+ htIndex.value += 1
366
+ indexRefs[sign].value = index
367
+ htTooltip.value?.setTooltipContent(TTContent(next))
368
+ }
369
+
370
+ const bindPickEvent = (target, index) => {
371
+ if (!target) {
372
+ return
373
+ }
374
+
375
+ target.on('click', () => {
376
+ const length = polygon.value.getLatLngs()[0].length
377
+
378
+ if (htIndex.value === 1) {
379
+ doPickMarker(index)
380
+ const leftIndex = index === length - 1 ? 0 : index + 1
381
+ const rightIndex = index === 0 ? length - 1 : index - 1
382
+ for (const [key, marker] of htHelpMarkers) {
383
+ if (key !== leftIndex && key !== rightIndex) {
384
+ htHelpCacheItems.addLayer(marker)
385
+ htHelpItems.removeLayer(marker)
386
+ }
387
+ }
388
+ } else if (htIndex.value === 2) {
389
+ doPickMarker(index)
390
+ htHelpMarkers.delete(index)
391
+ htHelpCacheItems.eachLayer((layer) => {
392
+ layer.addTo(htHelpItems)
393
+ htHelpCacheItems.removeLayer(layer)
394
+ })
395
+
396
+ let directionPositive = hsIndex.value < tsIndex.value
397
+ if (Math.abs(hsIndex.value - tsIndex.value) === length - 1) {
398
+ directionPositive = tsIndex.value === 0
399
+ }
400
+
401
+ if (htHelpMarkers.size === 2) {
402
+ const nextHeIndex = adjustIndex(directionPositive ? hsIndex.value - 1 : hsIndex.value + 1, length)
403
+ doPickMarker(nextHeIndex)
404
+ const nextTeIndex = adjustIndex(directionPositive ? tsIndex.value + 1 : tsIndex.value - 1, length)
405
+ doPickMarker(nextTeIndex)
406
+ finishPick()
407
+ } else {
408
+ const banIndex = adjustIndex(directionPositive ? tsIndex.value + 1 : tsIndex.value - 1, length)
409
+ const banMarker = htHelpMarkers.get(banIndex)
410
+ htHelpCacheItems.addLayer(banMarker)
411
+ htHelpItems.removeLayer(banMarker)
412
+ }
413
+ } else if (htIndex.value === 3) {
414
+ doPickMarker(index)
415
+ htHelpMarkers.delete(index)
416
+ htHelpCacheItems.eachLayer((layer) => {
417
+ htHelpCacheItems.removeLayer(layer)
418
+ layer.addTo(htHelpItems)
419
+ })
420
+
421
+ let directionPositive = hsIndex.value < tsIndex.value
422
+ if (Math.abs(hsIndex.value - tsIndex.value) === length - 1) {
423
+ directionPositive = tsIndex.value === 0
424
+ }
425
+
426
+ const banIndex = []
427
+ if (directionPositive) {
428
+ const tempEnd = hsIndex.value < index ? hsIndex.value + length : hsIndex.value
429
+ for (let current = index + 1; current < tempEnd; current += 1) {
430
+ banIndex.push(current > length - 1 ? current - length : current)
431
+ }
432
+ } else {
433
+ const tempEnd = hsIndex.value > index ? index + length : index
434
+ for (let current = hsIndex.value + 1; current < tempEnd; current += 1) {
435
+ banIndex.push(current > length - 1 ? current - length : current)
436
+ }
437
+ }
438
+
439
+ banIndex.forEach((value) => {
440
+ const banMarker = htHelpMarkers.get(value)
441
+ htHelpCacheItems.addLayer(banMarker)
442
+ htHelpItems.removeLayer(banMarker)
443
+ })
444
+
445
+ if (length - banIndex.length - 3 === 1) {
446
+ for (const key of htHelpMarkers.keys()) {
447
+ if (_.indexOf(banIndex, key) < 0) {
448
+ doPickMarker(key)
449
+ finishPick()
450
+ break
451
+ }
452
+ }
453
+ }
454
+ } else if (htIndex.value === 4) {
455
+ doPickMarker(index)
456
+ finishPick()
457
+ }
458
+ })
459
+ }
460
+
461
+ const saveItems = () => {
462
+ if (!saveReady.value) {
463
+ return
464
+ }
465
+
466
+ if (drawStatus.value === 'reset') {
467
+ emit('on-save', { latLngs: null, htIndex: null })
468
+ } else if (drawStatus.value === 'finish') {
469
+ emit('on-save', {
470
+ latLngs: polygon.value.getLatLngs()[0],
471
+ htIndex: [hsIndex.value, tsIndex.value, heIndex.value, teIndex.value]
472
+ })
473
+ }
474
+ }
475
+
476
+ const actionDisabled = (action) => {
477
+ if (action === 'draw') {
478
+ return drawReady.value ? null : 'disabled'
479
+ }
480
+ if (action === 'edit') {
481
+ return editReady.value ? null : 'disabled'
482
+ }
483
+ if (action === 'drag') {
484
+ return dragReady.value ? null : 'disabled'
485
+ }
486
+ if (action === 'pick') {
487
+ return pickReady.value ? null : 'disabled'
488
+ }
489
+ if (action === 'save') {
490
+ return saveReady.value ? null : 'disabled'
491
+ }
492
+ return null
493
+ }
494
+
495
+ defineExpose({
496
+ enable
497
+ })
498
+ </script>
@@ -0,0 +1,128 @@
1
+ <template>
2
+ <div class="vae-map-ctrl--draw">
3
+ <div class="item-group">
4
+ <div class="item" title="绘制">
5
+ <div class="item-icon fas fa-pen-alt" :class="actionDisabled('draw')" @click="startDrawMode" />
6
+ <div v-if="drawStatus === 'draw'" class="tooltips">
7
+ <span @click="drawStatus = 'none'">取消</span>
8
+ <span @click="removeLastVertx">移除上一个节点</span>
9
+ </div>
10
+ </div>
11
+ <div class="item" title="清除">
12
+ <div class="item-icon fas fa-trash-alt" @click="clearDrawItems" />
13
+ </div>
14
+ </div>
15
+ <div class="item-group">
16
+ <div class="item" title="保存">
17
+ <div class="item-icon fas fa-save" :class="actionDisabled('save')" @click="saveItems" />
18
+ </div>
19
+ </div>
20
+ </div>
21
+ </template>
22
+
23
+ <script setup>
24
+ import { computed, ref, watch } from 'vue'
25
+ import { ElMessage } from 'element-plus'
26
+
27
+ defineOptions({
28
+ name: 'VaeMapCtrlDrawLine'
29
+ })
30
+
31
+ const emit = defineEmits(['on-create', 'on-save'])
32
+
33
+ const enabled = ref(false)
34
+ const mapInstance = ref(null)
35
+ const drawItems = L.layerGroup()
36
+ const drawStatus = ref('none')
37
+ const polyline = ref(null)
38
+
39
+ watch(drawStatus, (value) => {
40
+ if (value === 'none') {
41
+ quitDrawMode()
42
+ }
43
+ })
44
+
45
+ const enable = (map, data) => {
46
+ if (!map) {
47
+ return
48
+ }
49
+
50
+ enabled.value = true
51
+ mapInstance.value = map
52
+ mapInstance.value.pm.setLang('zh')
53
+ drawItems.addTo(mapInstance.value)
54
+ mapInstance.value.on('pm:create', ({ shape, layer }) => {
55
+ layer.remove()
56
+ layer.addTo(drawItems)
57
+ if (shape === 'Line') {
58
+ if (polyline.value) {
59
+ polyline.value.remove()
60
+ }
61
+ polyline.value = layer
62
+ drawStatus.value = 'none'
63
+ ElMessage.success('绘制完成')
64
+ emit('on-create', polyline.value)
65
+ }
66
+ })
67
+
68
+ if (data?.latLngs && data.latLngs.length > 1) {
69
+ polyline.value = L.polyline(data.latLngs).addTo(drawItems)
70
+ emit('on-create', polyline.value)
71
+ }
72
+ }
73
+
74
+ const clearDrawItems = () => {
75
+ drawStatus.value = 'none'
76
+ drawItems.clearLayers()
77
+ polyline.value = null
78
+ ElMessage.success('已清理')
79
+ }
80
+
81
+ const startDrawMode = () => {
82
+ if (drawReady.value) {
83
+ mapInstance.value.pm.enableDraw('Line')
84
+ drawStatus.value = 'draw'
85
+ }
86
+ }
87
+
88
+ const removeLastVertx = () => {
89
+ const target = mapInstance.value.pm.Draw.Line
90
+ target._removeLastVertex()
91
+ if (!target._enabled) {
92
+ drawStatus.value = 'none'
93
+ }
94
+ }
95
+
96
+ const quitDrawMode = () => {
97
+ mapInstance.value?.pm.disableDraw('Line')
98
+ }
99
+
100
+ const saveItems = () => {
101
+ if (!saveReady.value) {
102
+ return
103
+ }
104
+
105
+ if (polyline.value) {
106
+ emit('on-save', { latLngs: polyline.value.getLatLngs() })
107
+ } else {
108
+ emit('on-save', { latLngs: null })
109
+ }
110
+ }
111
+
112
+ const actionDisabled = (action) => {
113
+ if (action === 'draw') {
114
+ return drawReady.value ? null : 'disabled'
115
+ }
116
+ if (action === 'save') {
117
+ return saveReady.value ? null : 'disabled'
118
+ }
119
+ return null
120
+ }
121
+
122
+ const drawReady = computed(() => enabled.value)
123
+ const saveReady = computed(() => enabled.value)
124
+
125
+ defineExpose({
126
+ enable
127
+ })
128
+ </script>
@@ -0,0 +1,59 @@
1
+ import VaeMap from './vae-map.jsx'
2
+ import VaeLrmap from './vae-lrmap.jsx'
3
+ import VaeMapCtrlDraw from './ctrl-draw/index.vue'
4
+ import VaeMapCtrlDrawLine from './ctrl-draw-line/index.vue'
5
+ import './style.less'
6
+
7
+ import 'leaflet'
8
+ import 'leaflet/dist/leaflet.css'
9
+ import markerIcon2x from 'leaflet/dist/images/marker-icon-2x.png'
10
+ import markerIcon from 'leaflet/dist/images/marker-icon.png'
11
+ import markerShadow from 'leaflet/dist/images/marker-shadow.png'
12
+
13
+ import './scripts/L.Vae.CRS'
14
+ import './scripts/L.Vae.Client'
15
+
16
+ import 'leaflet.markercluster'
17
+ import 'leaflet.markercluster/dist/MarkerCluster.css'
18
+ import 'leaflet.markercluster/dist/MarkerCluster.Default.css'
19
+
20
+ import 'leaflet-geometryutil'
21
+ import 'proj4'
22
+ import 'proj4leaflet'
23
+ import '@geoman-io/leaflet-geoman-free'
24
+ import '@geoman-io/leaflet-geoman-free/dist/leaflet-geoman.css'
25
+
26
+ import '@/plugins/L.AnimatedMarker'
27
+ import '@/plugins/L.EchartsLayer'
28
+ import '@/plugins/L.ElasticMarker'
29
+ import '@/plugins/L.FootageCalculator.Area'
30
+ import '@/plugins/L.FootageCalculator.Line'
31
+ import '@/plugins/L.GeoUtil'
32
+ import '@/plugins/L.Glyphicon'
33
+ import '@/plugins/L.MarkerClusterX'
34
+ import '@/plugins/L.TileLayer.ChinaProvider'
35
+ import '@/plugins/L.VuePopup'
36
+ import '@/plugins/L.VueTooltip'
37
+ import '@/plugins/L.SafeDivOverlay'
38
+
39
+ const resetDefaultMarkerIcon = () => {
40
+ delete L.Icon.Default.prototype._getIconUrl
41
+
42
+ L.Icon.Default.mergeOptions({
43
+ iconRetinaUrl: markerIcon2x,
44
+ iconUrl: markerIcon,
45
+ shadowUrl: markerShadow
46
+ })
47
+ }
48
+
49
+ const install = (app, options = {}) => {
50
+ app.component(`${options.prefix || 'vae'}-map`, VaeMap)
51
+ app.component(`${options.prefix || 'vae'}-lrmap`, VaeLrmap)
52
+ app.component(`${options.prefix || 'vae'}-map-ctrl-draw`, VaeMapCtrlDraw)
53
+ app.component(`${options.prefix || 'vae'}-map-ctrl-draw-line`, VaeMapCtrlDrawLine)
54
+ resetDefaultMarkerIcon()
55
+ }
56
+
57
+ export { VaeMap, VaeLrmap, VaeMapCtrlDraw, VaeMapCtrlDrawLine }
58
+
59
+ export default { install }