mapping-component-package-jp 0.0.57 → 0.1.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.d.ts +1 -0
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/js/mapEncapsulation/mapOverlayManager.d.ts +1 -0
- package/src/js/mapEncapsulation/mapOverlayManager.js +12 -0
- package/src/js/mapEncapsulation/shapes/circle.sector.js +26 -22
- package/src/js/mapEncapsulation/shapes/polygon.customedit.js +479 -393
|
@@ -1,393 +1,479 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
1
|
+
const handles = []
|
|
2
|
+
|
|
3
|
+
export class IQLPolygonCustomEdit {
|
|
4
|
+
constructor() {}
|
|
5
|
+
|
|
6
|
+
delete(map, currentPolygonCustomEdit) {
|
|
7
|
+
//console.log('polygon-custom-edit, delete, currentPolygonCustomEdit', currentPolygonCustomEdit);
|
|
8
|
+
|
|
9
|
+
if (!currentPolygonCustomEdit) return null
|
|
10
|
+
const path = currentPolygonCustomEdit.getPath()
|
|
11
|
+
//console.log('currentPolygonCustomEdit.delete, path', path);
|
|
12
|
+
const len = path.getLength()
|
|
13
|
+
//console.log('currentPolygonCustomEdit.delete, len', len);
|
|
14
|
+
|
|
15
|
+
for (let i = 0; i < len; i++) {
|
|
16
|
+
const handle = handles[i]
|
|
17
|
+
if (!handle) continue
|
|
18
|
+
|
|
19
|
+
if (handle.ghostMarker) {
|
|
20
|
+
google.maps.event.clearInstanceListeners(handle.ghostMarker)
|
|
21
|
+
handle.ghostMarker.setMap(null)
|
|
22
|
+
delete handle.ghostMarker.marker
|
|
23
|
+
delete handle.ghostMarker
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (handle.marker) {
|
|
27
|
+
google.maps.event.clearInstanceListeners(handle.marker)
|
|
28
|
+
handle.marker.setMap(null)
|
|
29
|
+
handle.marker = null
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
handles.length = 0
|
|
34
|
+
|
|
35
|
+
return currentPolygonCustomEdit
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
edit(map, polygon, currentPolygonCustomEdit, isMobile) {
|
|
39
|
+
let pointIcon
|
|
40
|
+
let midPointIcon
|
|
41
|
+
let handleIconUp
|
|
42
|
+
let handleIconDown
|
|
43
|
+
|
|
44
|
+
if (isMobile) {
|
|
45
|
+
const svgpi =
|
|
46
|
+
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">' +
|
|
47
|
+
'<path fill="rgba(255,255,255,0.01)" d="M 0, 24 a 24,24 0 1,0 48,0 a 24,24 0 1,0 -48,0" />' +
|
|
48
|
+
'<path fill="rgba(255,255,255,1)" stroke="#303030" stroke-width="1" d="M24 24 m-4,0 a 4,4,0 0,1 8,0 a 4,4 0 0,1 -8,0z" />' +
|
|
49
|
+
"</svg>"
|
|
50
|
+
|
|
51
|
+
pointIcon = {
|
|
52
|
+
url: "data:image/svg+xml;charset=UTF-8;base64," + btoa(svgpi),
|
|
53
|
+
anchor: new google.maps.Point(24, 24)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const svgmpi =
|
|
57
|
+
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">' +
|
|
58
|
+
'<path fill="rgba(255,255,255,0.01)" d="M 0, 24 a 24,24 0 1,0 48,0 a 24,24 0 1,0 -48,0" />' +
|
|
59
|
+
'<path fill="rgba(255,255,255,0.4)" stroke="#303030" stroke-width="0.3" stroke-opacity="0.01" d="M24 24 m-4,0 a 4,4,0 0,1 8,0 a 4,4 0 0,1 -8,0z" />' +
|
|
60
|
+
"</svg>"
|
|
61
|
+
|
|
62
|
+
midPointIcon = {
|
|
63
|
+
url: "data:image/svg+xml;charset=UTF-8;base64," + btoa(svgmpi),
|
|
64
|
+
anchor: new google.maps.Point(24, 24)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const svgup =
|
|
68
|
+
'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52">' +
|
|
69
|
+
'<g transform="scale(0.4 0.4)">' +
|
|
70
|
+
'<path style="fill:#f1a81e;" d="M38.853,5.324L38.853,5.324c-7.098-7.098-18.607-7.098-25.706,0h0 C6.751,11.72,6.031,23.763,11.459,31L26,52l14.541-21C45.969,23.763,45.249,11.72,38.853,5.324z"/>' +
|
|
71
|
+
'<g transform="translate(13.2 5.9) scale(0.8 0.8)">' +
|
|
72
|
+
// (paths trimmed for brevity—same as your JS)
|
|
73
|
+
"</g></g></svg>"
|
|
74
|
+
|
|
75
|
+
handleIconUp = {
|
|
76
|
+
url: "data:image/svg+xml;charset=UTF-8;base64," + btoa(svgup),
|
|
77
|
+
anchor: new google.maps.Point(30, 60)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const svgdown =
|
|
81
|
+
'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52">' +
|
|
82
|
+
'<g transform="scale(0.4 0.4) rotate(180 26 26)">' +
|
|
83
|
+
'<path style="fill:#f1a81e;" d="M38.853,5.324L38.853,5.324c-7.098-7.098-18.607-7.098-25.706,0h0 C6.751,11.72,6.031,23.763,11.459,31L26,52l14.541-21C45.969,23.763,45.249,11.72,38.853,5.324z"/>' +
|
|
84
|
+
'<g transform="translate(13.2 5.9) scale(0.8 0.8)">' +
|
|
85
|
+
// (paths trimmed for brevity—same as your JS)
|
|
86
|
+
"</g></g></svg>"
|
|
87
|
+
|
|
88
|
+
handleIconDown = {
|
|
89
|
+
url: "data:image/svg+xml;charset=UTF-8;base64," + btoa(svgdown),
|
|
90
|
+
anchor: new google.maps.Point(30, 0)
|
|
91
|
+
}
|
|
92
|
+
} else {
|
|
93
|
+
pointIcon = {
|
|
94
|
+
path: "M4 4m-4,0a4,4,0 0,1 8,0a 4,4 0 0,1 -8,0z",
|
|
95
|
+
fillColor: "#ffffff",
|
|
96
|
+
fillOpacity: 1,
|
|
97
|
+
anchor: new google.maps.Point(4, 4),
|
|
98
|
+
strokeWeight: 1,
|
|
99
|
+
strokeOpacity: 1,
|
|
100
|
+
strokeColor: "#303030",
|
|
101
|
+
scale: 1
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
midPointIcon = {
|
|
105
|
+
path: "M4 4m-4,0a4,4,0 0,1 8,0a 4,4 0 0,1 -8,0z",
|
|
106
|
+
fillColor: "#ffffff",
|
|
107
|
+
fillOpacity: 0.4,
|
|
108
|
+
anchor: new google.maps.Point(4, 4),
|
|
109
|
+
strokeWeight: 0.3,
|
|
110
|
+
strokeOpacity: 0.01,
|
|
111
|
+
strokeColor: "#303030",
|
|
112
|
+
scale: 1
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const ghostPath = new google.maps.Polyline({
|
|
117
|
+
map,
|
|
118
|
+
strokeColor: "#ffff00",
|
|
119
|
+
strokeOpacity: 0.6,
|
|
120
|
+
strokeWeight: 2,
|
|
121
|
+
clickable: false,
|
|
122
|
+
zIndex: 10100
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
const vertexGhostDragStart = function() {
|
|
126
|
+
for (let i = 0; i < handles.length; i++) {
|
|
127
|
+
const m = handles[i]?.marker
|
|
128
|
+
if (m) m.setIcon(pointIcon)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const path = polygon.getPath()
|
|
132
|
+
const bounds = new google.maps.LatLngBounds()
|
|
133
|
+
for (let i = 0, len = path.getLength(); i < len; i++) {
|
|
134
|
+
bounds.extend(path.getAt(i))
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (isMobile && handleIconUp && handleIconDown) {
|
|
138
|
+
const center = bounds.getCenter()
|
|
139
|
+
const pos = this.getPosition()
|
|
140
|
+
if (!pos) return
|
|
141
|
+
this.setIcon(pos.lat() >= center.lat() ? handleIconUp : handleIconDown)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const vertexGhostDrag = function() {
|
|
146
|
+
const idx = this.marker.editIndex
|
|
147
|
+
const path = polygon.getPath()
|
|
148
|
+
const lastIndex = path.getLength() - 1
|
|
149
|
+
|
|
150
|
+
const from = this.marker.getPosition()
|
|
151
|
+
const current = this.getPosition()
|
|
152
|
+
const third = idx < lastIndex ? path.getAt(idx + 1) : path.getAt(0)
|
|
153
|
+
|
|
154
|
+
if (ghostPath.getPath().getLength() === 0) {
|
|
155
|
+
ghostPath.setPath([from, current, third])
|
|
156
|
+
} else {
|
|
157
|
+
ghostPath.getPath().setAt(1, current)
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const vertexGhostDragEnd = function() {
|
|
162
|
+
const linked = this.marker
|
|
163
|
+
if (!linked) return
|
|
164
|
+
const pos = this.getPosition()
|
|
165
|
+
if (!pos) return
|
|
166
|
+
|
|
167
|
+
const path = polygon.getPath()
|
|
168
|
+
const len = path.getLength()
|
|
169
|
+
if (len < 1) return
|
|
170
|
+
|
|
171
|
+
const i = linked.editIndex
|
|
172
|
+
const insertIdx = i === len - 1 ? 0 : i + 1
|
|
173
|
+
|
|
174
|
+
// Capture the original handle that owns this ghost BEFORE mutating handles
|
|
175
|
+
const originalHandle = handles[i]
|
|
176
|
+
|
|
177
|
+
// 1) Remove the dragged ghost instance itself
|
|
178
|
+
google.maps.event.clearInstanceListeners(this)
|
|
179
|
+
this.setMap(null)
|
|
180
|
+
|
|
181
|
+
// 2) Insert the new vertex at the ghost position
|
|
182
|
+
path.insertAt(insertIdx, pos)
|
|
183
|
+
|
|
184
|
+
// 3) Create the new vertex marker and splice into handles
|
|
185
|
+
const newVertexMarker = new google.maps.Marker({
|
|
186
|
+
map,
|
|
187
|
+
icon: pointIcon,
|
|
188
|
+
draggable: true,
|
|
189
|
+
raiseOnDrag: false,
|
|
190
|
+
position: pos
|
|
191
|
+
})
|
|
192
|
+
google.maps.event.addListener(
|
|
193
|
+
newVertexMarker,
|
|
194
|
+
"dragstart",
|
|
195
|
+
vertexDragStart
|
|
196
|
+
)
|
|
197
|
+
google.maps.event.addListener(newVertexMarker, "drag", vertexDrag)
|
|
198
|
+
google.maps.event.addListener(newVertexMarker, "dragend", vertexDragEnd)
|
|
199
|
+
|
|
200
|
+
handles.splice(insertIdx, 0, {
|
|
201
|
+
marker: newVertexMarker,
|
|
202
|
+
ghostMarker: undefined
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
// 4) Update editIndex for all markers from insertIdx onward
|
|
206
|
+
for (let k = insertIdx; k < handles.length; k++) {
|
|
207
|
+
const m = handles[k]?.marker
|
|
208
|
+
if (m) m.editIndex = k
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// 5) Clean up the original handle's ghost (the one on edge i→i+1),
|
|
212
|
+
// but ONLY if it’s not the same instance as the dragged ghost
|
|
213
|
+
const gh = originalHandle?.ghostMarker
|
|
214
|
+
if (gh && gh !== this) {
|
|
215
|
+
google.maps.event.clearInstanceListeners(gh)
|
|
216
|
+
gh.setMap(null)
|
|
217
|
+
delete gh.marker
|
|
218
|
+
delete originalHandle.ghostMarker
|
|
219
|
+
} else if (originalHandle) {
|
|
220
|
+
// Ensure the property is gone to force recreation
|
|
221
|
+
delete originalHandle?.ghostMarker
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// 6) Recreate ONLY the two ghosts adjacent to the new vertex
|
|
225
|
+
const prevIndex = insertIdx === 0 ? path.getLength() - 1 : insertIdx - 1
|
|
226
|
+
createGhostMarkerVertex(prevIndex) // between previous vertex and new vertex
|
|
227
|
+
createGhostMarkerVertex(insertIdx) // between new vertex and next vertex
|
|
228
|
+
|
|
229
|
+
// 7) Clear the visual helper polyline
|
|
230
|
+
while (ghostPath.getPath().getLength() > 0) ghostPath.getPath().pop()
|
|
231
|
+
|
|
232
|
+
// 8) Notify consumers
|
|
233
|
+
google.maps.event.trigger(polygon, "insert_at", insertIdx, pos)
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const vertexDragStart = function() {
|
|
237
|
+
for (let i = 0; i < handles.length; i++) {
|
|
238
|
+
const m = handles[i]?.marker
|
|
239
|
+
if (m) m.setIcon(pointIcon)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const path = polygon.getPath()
|
|
243
|
+
const bounds = new google.maps.LatLngBounds()
|
|
244
|
+
for (let i = 0, len = path.getLength(); i < len; i++) {
|
|
245
|
+
bounds.extend(path.getAt(i))
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (isMobile && handleIconUp && handleIconDown) {
|
|
249
|
+
const center = bounds.getCenter()
|
|
250
|
+
const pos = this.getPosition()
|
|
251
|
+
if (!pos) return
|
|
252
|
+
this.setIcon(pos.lat() >= center.lat() ? handleIconUp : handleIconDown)
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const vertexDrag = function() {
|
|
257
|
+
const idx = this.editIndex
|
|
258
|
+
const pos = this.getPosition()
|
|
259
|
+
polygon.getPath().setAt(idx, pos)
|
|
260
|
+
|
|
261
|
+
const path = polygon.getPath()
|
|
262
|
+
const prevIdx = idx === 0 ? path.getLength() - 1 : idx - 1
|
|
263
|
+
|
|
264
|
+
createGhostMarkerVertex(prevIdx)
|
|
265
|
+
createGhostMarkerVertex(idx)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const vertexDragEnd = function() {
|
|
269
|
+
google.maps.event.trigger(
|
|
270
|
+
polygon,
|
|
271
|
+
"update_at",
|
|
272
|
+
this.editIndex,
|
|
273
|
+
this.getPosition()
|
|
274
|
+
)
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const vertexRightClick = function() {
|
|
278
|
+
const path = polygon.getPath()
|
|
279
|
+
const len = path.getLength()
|
|
280
|
+
if (len === 0) return
|
|
281
|
+
|
|
282
|
+
const i = this.editIndex
|
|
283
|
+
const prevIdx = i === 0 ? len - 1 : i - 1
|
|
284
|
+
|
|
285
|
+
const gm = handles[i]?.ghostMarker
|
|
286
|
+
if (gm) {
|
|
287
|
+
google.maps.event.clearInstanceListeners(gm)
|
|
288
|
+
gm.setMap(null)
|
|
289
|
+
delete gm.marker // clear back-reference
|
|
290
|
+
delete handles[i].ghostMarker
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const removedLL = path.getAt(i)
|
|
294
|
+
path.removeAt(i)
|
|
295
|
+
google.maps.event.clearInstanceListeners(this)
|
|
296
|
+
this.setMap(null)
|
|
297
|
+
|
|
298
|
+
handles.splice(i, 1)
|
|
299
|
+
|
|
300
|
+
const newLen = path.getLength()
|
|
301
|
+
|
|
302
|
+
if (newLen >= 2) {
|
|
303
|
+
let adjPrevIdx = prevIdx
|
|
304
|
+
if (prevIdx > i) adjPrevIdx = prevIdx - 1
|
|
305
|
+
|
|
306
|
+
const prevLL = path.getAt(adjPrevIdx)
|
|
307
|
+
const newNextIdx = adjPrevIdx === newLen - 1 ? 0 : adjPrevIdx + 1
|
|
308
|
+
const nextLL = path.getAt(newNextIdx)
|
|
309
|
+
|
|
310
|
+
const prevHandle = handles[adjPrevIdx]
|
|
311
|
+
if (prevHandle?.ghostMarker && prevLL && nextLL) {
|
|
312
|
+
const midPos = google.maps.geometry
|
|
313
|
+
? google.maps.geometry.spherical.interpolate(prevLL, nextLL, 0.5)
|
|
314
|
+
: new google.maps.LatLng(
|
|
315
|
+
prevLL.lat() + 0.5 * (nextLL.lat() - prevLL.lat()),
|
|
316
|
+
prevLL.lng() + 0.5 * (nextLL.lng() - prevLL.lng())
|
|
317
|
+
)
|
|
318
|
+
prevHandle.ghostMarker.setPosition(midPos)
|
|
319
|
+
}
|
|
320
|
+
} else {
|
|
321
|
+
if (newLen === 1) {
|
|
322
|
+
const onlyHandle = handles[0]
|
|
323
|
+
|
|
324
|
+
if (onlyHandle?.ghostMarker) {
|
|
325
|
+
google.maps.event.clearInstanceListeners(onlyHandle.ghostMarker)
|
|
326
|
+
onlyHandle.ghostMarker.setMap(null)
|
|
327
|
+
delete onlyHandle.ghostMarker.marker
|
|
328
|
+
delete onlyHandle.ghostMarker
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (onlyHandle?.marker) {
|
|
332
|
+
google.maps.event.clearInstanceListeners(onlyHandle.marker)
|
|
333
|
+
onlyHandle.marker.setMap(null)
|
|
334
|
+
onlyHandle.marker = null
|
|
335
|
+
}
|
|
336
|
+
path.removeAt(0)
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
for (let idx = 0; idx < handles.length; idx++) {
|
|
341
|
+
const m = handles[idx]?.marker
|
|
342
|
+
if (m) m.editIndex = idx
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
google.maps.event.trigger(polygon, "remove_at", i, removedLL)
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const createMarkerVertex = (index, icon) => {
|
|
349
|
+
const ll = polygon.getPath().getAt(index)
|
|
350
|
+
|
|
351
|
+
let vm = handles[index]?.marker
|
|
352
|
+
if (!vm) {
|
|
353
|
+
vm = new google.maps.Marker({
|
|
354
|
+
position: ll,
|
|
355
|
+
map,
|
|
356
|
+
icon,
|
|
357
|
+
draggable: true,
|
|
358
|
+
raiseOnDrag: false
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
google.maps.event.addListener(vm, "dragstart", vertexDragStart)
|
|
362
|
+
google.maps.event.addListener(vm, "drag", vertexDrag)
|
|
363
|
+
google.maps.event.addListener(vm, "dragend", vertexDragEnd)
|
|
364
|
+
//google.maps.event.addListener(vm, 'rightclick', vertexRightClick); // if you want delete
|
|
365
|
+
|
|
366
|
+
vm.editIndex = index
|
|
367
|
+
handles[index] = { marker: vm } // create the VertexHandle
|
|
368
|
+
} else {
|
|
369
|
+
vm.setPosition(ll)
|
|
370
|
+
vm.editIndex = index
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
return vm
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
const createGhostMarkerVertex = index => {
|
|
377
|
+
const path = polygon.getPath()
|
|
378
|
+
const pathLen = path.getLength()
|
|
379
|
+
if (pathLen < 2) return null
|
|
380
|
+
|
|
381
|
+
const currLL = path.getAt(index)
|
|
382
|
+
const nextIndex = index < pathLen - 1 ? index + 1 : 0
|
|
383
|
+
const nextLL = path.getAt(nextIndex)
|
|
384
|
+
const midPos = !google.maps.geometry
|
|
385
|
+
? new google.maps.LatLng(
|
|
386
|
+
currLL.lat() + 0.5 * (nextLL.lat() - currLL.lat()),
|
|
387
|
+
currLL.lng() + 0.5 * (nextLL.lng() - currLL.lng())
|
|
388
|
+
)
|
|
389
|
+
: google.maps.geometry.spherical.interpolate(currLL, nextLL, 0.5)
|
|
390
|
+
|
|
391
|
+
const vertexMarker = handles[index]?.marker
|
|
392
|
+
if (!vertexMarker) return null
|
|
393
|
+
|
|
394
|
+
let gm = handles[index]?.ghostMarker
|
|
395
|
+
|
|
396
|
+
// Recreate if missing OR removed from map (e.g., after dragend cleanup)
|
|
397
|
+
if (!gm || gm.getMap() === null) {
|
|
398
|
+
gm = new google.maps.Marker({
|
|
399
|
+
map,
|
|
400
|
+
icon: midPointIcon,
|
|
401
|
+
draggable: true,
|
|
402
|
+
raiseOnDrag: false
|
|
403
|
+
})
|
|
404
|
+
gm.marker = vertexMarker
|
|
405
|
+
google.maps.event.addListener(gm, "dragstart", vertexGhostDragStart)
|
|
406
|
+
google.maps.event.addListener(gm, "drag", vertexGhostDrag)
|
|
407
|
+
google.maps.event.addListener(gm, "dragend", vertexGhostDragEnd)
|
|
408
|
+
handles[index].ghostMarker = gm
|
|
409
|
+
} else {
|
|
410
|
+
// keep the back-reference correct
|
|
411
|
+
gm.marker = vertexMarker
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
gm.setPosition(midPos)
|
|
415
|
+
return gm
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
const syncMarkersToPolygonPath = () => {
|
|
420
|
+
const path = polygon.getPath()
|
|
421
|
+
for (let i = 0; i < path.getLength(); i++) {
|
|
422
|
+
const ll = path.getAt(i)
|
|
423
|
+
const vh = handles[i]
|
|
424
|
+
if (!vh) continue
|
|
425
|
+
|
|
426
|
+
const m = vh.marker
|
|
427
|
+
if (m) {
|
|
428
|
+
m.setPosition(ll)
|
|
429
|
+
m.editIndex = i
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
createGhostMarkerVertex(i)
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
const setVertexAndGhostMarkersDraggable = draggable => {
|
|
437
|
+
for (let i = 0; i < handles.length; i++) {
|
|
438
|
+
const vh = handles[i]
|
|
439
|
+
vh?.marker?.setDraggable(draggable)
|
|
440
|
+
vh?.ghostMarker?.setDraggable(draggable)
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
google.maps.event.addListener(polygon, "dragstart", () => {
|
|
445
|
+
setVertexAndGhostMarkersDraggable(false)
|
|
446
|
+
})
|
|
447
|
+
|
|
448
|
+
google.maps.event.addListener(polygon, "drag", () => {
|
|
449
|
+
syncMarkersToPolygonPath()
|
|
450
|
+
})
|
|
451
|
+
|
|
452
|
+
google.maps.event.addListener(polygon, "dragend", () => {
|
|
453
|
+
syncMarkersToPolygonPath()
|
|
454
|
+
setVertexAndGhostMarkersDraggable(true)
|
|
455
|
+
})
|
|
456
|
+
|
|
457
|
+
function PolygonCustomEditWidget(map, polygon, currentPolygonCustomEdit, isMobile) {
|
|
458
|
+
|
|
459
|
+
polygon.setMap(map)
|
|
460
|
+
|
|
461
|
+
polygon.getPath().forEach((_vertexLL, index) => {
|
|
462
|
+
const iconForThisVertex = isMobile && handleIconUp && index === 1 ? handleIconUp : pointIcon
|
|
463
|
+
const vm = createMarkerVertex(index, iconForThisVertex)
|
|
464
|
+
vm.editIndex = index
|
|
465
|
+
|
|
466
|
+
createGhostMarkerVertex(index);
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
currentPolygonCustomEdit = polygon;
|
|
470
|
+
|
|
471
|
+
return currentPolygonCustomEdit;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
PolygonCustomEditWidget.prototype = new google.maps.MVCObject();
|
|
475
|
+
|
|
476
|
+
return new PolygonCustomEditWidget(map, polygon, currentPolygonCustomEdit, isMobile);
|
|
477
|
+
|
|
478
|
+
}
|
|
479
|
+
}
|