@syncfusion/ej2-maps 19.4.55 → 19.4.56-105067

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 (84) hide show
  1. package/.eslintrc.json +18 -3
  2. package/.github/PULL_REQUEST_TEMPLATE/Bug.md +72 -72
  3. package/.github/PULL_REQUEST_TEMPLATE/Feature.md +49 -49
  4. package/CHANGELOG.md +441 -430
  5. package/README.md +73 -73
  6. package/dist/ej2-maps.umd.min.js +1 -10
  7. package/dist/ej2-maps.umd.min.js.map +1 -1
  8. package/dist/es6/ej2-maps.es2015.js +1205 -644
  9. package/dist/es6/ej2-maps.es2015.js.map +1 -1
  10. package/dist/es6/ej2-maps.es5.js +1243 -683
  11. package/dist/es6/ej2-maps.es5.js.map +1 -1
  12. package/dist/global/ej2-maps.min.js +1 -10
  13. package/dist/global/ej2-maps.min.js.map +1 -1
  14. package/dist/global/index.d.ts +0 -9
  15. package/dist/ts/maps/layers/bing-map.ts +50 -0
  16. package/dist/ts/maps/layers/bubble.ts +290 -0
  17. package/dist/ts/maps/layers/color-mapping.ts +226 -0
  18. package/dist/ts/maps/layers/data-label.ts +418 -0
  19. package/dist/ts/maps/layers/layer-panel.ts +1480 -0
  20. package/dist/ts/maps/layers/legend.ts +2236 -0
  21. package/dist/ts/maps/layers/marker.ts +453 -0
  22. package/dist/ts/maps/layers/navigation-selected-line.ts +167 -0
  23. package/dist/ts/maps/maps.ts +2886 -0
  24. package/dist/ts/maps/model/base.ts +1843 -0
  25. package/dist/ts/maps/model/constants.ts +200 -0
  26. package/dist/ts/maps/model/export-image.ts +178 -0
  27. package/dist/ts/maps/model/export-pdf.ts +170 -0
  28. package/dist/ts/maps/model/interface.ts +823 -0
  29. package/dist/ts/maps/model/print.ts +104 -0
  30. package/dist/ts/maps/model/theme.ts +554 -0
  31. package/dist/ts/maps/user-interaction/annotation.ts +127 -0
  32. package/dist/ts/maps/user-interaction/highlight.ts +233 -0
  33. package/dist/ts/maps/user-interaction/selection.ts +321 -0
  34. package/dist/ts/maps/user-interaction/tooltip.ts +387 -0
  35. package/dist/ts/maps/user-interaction/zoom.ts +1767 -0
  36. package/dist/ts/maps/utils/enum.ts +368 -0
  37. package/dist/ts/maps/utils/helper.ts +3421 -0
  38. package/helper/e2e/index.js +3 -3
  39. package/helper/e2e/maps-helper.js +13 -13
  40. package/license +9 -9
  41. package/package.json +85 -85
  42. package/src/maps/layers/bing-map.d.ts +4 -0
  43. package/src/maps/layers/bing-map.js +16 -3
  44. package/src/maps/layers/bubble.d.ts +1 -2
  45. package/src/maps/layers/bubble.js +7 -12
  46. package/src/maps/layers/data-label.d.ts +1 -4
  47. package/src/maps/layers/data-label.js +32 -35
  48. package/src/maps/layers/layer-panel.d.ts +18 -1
  49. package/src/maps/layers/layer-panel.js +226 -72
  50. package/src/maps/layers/legend.d.ts +5 -2
  51. package/src/maps/layers/legend.js +170 -61
  52. package/src/maps/layers/marker.d.ts +2 -4
  53. package/src/maps/layers/marker.js +49 -48
  54. package/src/maps/layers/navigation-selected-line.d.ts +1 -2
  55. package/src/maps/layers/navigation-selected-line.js +7 -13
  56. package/src/maps/maps-model.d.ts +259 -251
  57. package/src/maps/maps.d.ts +24 -3
  58. package/src/maps/maps.js +164 -97
  59. package/src/maps/model/base-model.d.ts +1025 -1021
  60. package/src/maps/model/base.d.ts +5 -1
  61. package/src/maps/model/base.js +24 -24
  62. package/src/maps/model/constants.d.ts +6 -0
  63. package/src/maps/model/constants.js +6 -0
  64. package/src/maps/model/export-image.d.ts +2 -4
  65. package/src/maps/model/export-image.js +34 -33
  66. package/src/maps/model/export-pdf.d.ts +4 -6
  67. package/src/maps/model/export-pdf.js +31 -32
  68. package/src/maps/model/interface.d.ts +34 -26
  69. package/src/maps/model/print.d.ts +2 -5
  70. package/src/maps/model/print.js +32 -18
  71. package/src/maps/model/theme.js +7 -4
  72. package/src/maps/user-interaction/annotation.d.ts +1 -2
  73. package/src/maps/user-interaction/annotation.js +3 -4
  74. package/src/maps/user-interaction/highlight.d.ts +1 -2
  75. package/src/maps/user-interaction/highlight.js +11 -10
  76. package/src/maps/user-interaction/selection.d.ts +1 -2
  77. package/src/maps/user-interaction/selection.js +42 -19
  78. package/src/maps/user-interaction/tooltip.d.ts +3 -5
  79. package/src/maps/user-interaction/tooltip.js +27 -14
  80. package/src/maps/user-interaction/zoom.d.ts +3 -8
  81. package/src/maps/user-interaction/zoom.js +282 -162
  82. package/src/maps/utils/enum.d.ts +5 -1
  83. package/src/maps/utils/helper.d.ts +9 -1
  84. package/src/maps/utils/helper.js +82 -33
@@ -0,0 +1,3421 @@
1
+ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
2
+ /* eslint-disable @typescript-eslint/no-unused-vars */
3
+ /* eslint-disable max-len */
4
+ /**
5
+ * Helper functions for maps control
6
+ */
7
+ import { createElement, isNullOrUndefined, remove, compile as templateComplier, merge } from '@syncfusion/ej2-base';
8
+ import { AnimationOptions, Animation } from '@syncfusion/ej2-base';
9
+ import { SvgRenderer } from '@syncfusion/ej2-svg-base';
10
+ import { Maps, FontModel, BorderModel, LayerSettings, ProjectionType, ISelectionEventArgs, itemSelection } from '../../index';
11
+ import { animationComplete, IAnimationCompleteEventArgs, Alignment, LayerSettingsModel } from '../index';
12
+ import {
13
+ MarkerType, IShapeSelectedEventArgs, ITouches, IShapes, SelectionSettingsModel,
14
+ MarkerClusterSettingsModel, IMarkerRenderingEventArgs, MarkerSettings, markerClusterRendering,
15
+ IMarkerClusterRenderingEventArgs, MarkerClusterData
16
+ } from '../index';
17
+ import { CenterPositionModel, ConnectorLineSettingsModel, MarkerSettingsModel } from '../model/base-model';
18
+ import { ExportType } from '../utils/enum';
19
+
20
+ /**
21
+ * Maps internal use of `Size` type
22
+ */
23
+ export class Size {
24
+ /**
25
+ * height value for size
26
+ */
27
+ public height: number;
28
+ /**
29
+ * width value for size
30
+ */
31
+ public width: number;
32
+
33
+ constructor(width: number, height: number) {
34
+ this.width = width;
35
+ this.height = height;
36
+ }
37
+ }
38
+ /**
39
+ * To find number from string
40
+ *
41
+ * @param {string} value Specifies the value
42
+ * @param {number} containerSize Specifies the container size
43
+ * @returns {number} Returns the number
44
+ * @private
45
+ */
46
+ export function stringToNumber(value: string, containerSize: number): number {
47
+ if (value !== null && value !== undefined) {
48
+ return value.indexOf('%') !== -1 ? (containerSize / 100) * parseInt(value, 10) : parseInt(value, 10);
49
+ }
50
+ return null;
51
+ }
52
+ /**
53
+ * Method to calculate the width and height of the maps
54
+ *
55
+ * @param {Maps} maps Specifies the maps instance
56
+ * @returns {void}
57
+ */
58
+ export function calculateSize(maps: Maps): Size {
59
+ maps.element.style.height = !isNullOrUndefined(maps.height) ? maps.height : 'auto';
60
+ maps.element.style.width = !isNullOrUndefined(maps.width) ? maps.width : 'auto';
61
+ const containerWidth: number = maps.element.clientWidth;
62
+ const containerHeight: number = maps.element.clientHeight;
63
+ const containerElementWidth: number = stringToNumber(maps.element.style.width, containerWidth);
64
+ const containerElementHeight: number = stringToNumber(maps.element.style.height, containerHeight);
65
+ let availableSize: Size = new Size(0,0);
66
+ if (maps.width === '0px' || maps.width === '0%' || maps.height === '0%' || maps.height === '0px') {
67
+ availableSize = new Size(0, 0);
68
+ } else {
69
+ availableSize = new Size(
70
+ stringToNumber(maps.width, containerWidth) || containerWidth || containerElementWidth || 600,
71
+ stringToNumber(maps.height, containerHeight) || containerHeight || containerElementHeight || (maps.isDevice ?
72
+ Math.min(window.innerWidth, window.innerHeight) : 450)
73
+ );
74
+ }
75
+ return availableSize;
76
+ }
77
+ /**
78
+ * Method to create svg for maps.
79
+ *
80
+ * @param {Maps} maps Specifies the map instance
81
+ * @returns {void}
82
+ */
83
+ export function createSvg(maps: Maps): void {
84
+ maps.renderer = new SvgRenderer(maps.element.id);
85
+ maps.availableSize = calculateSize(maps);
86
+ maps.svgObject = maps.renderer.createSvg({
87
+ id: maps.element.id + '_svg',
88
+ width: maps.availableSize.width,
89
+ height: maps.availableSize.height
90
+ });
91
+ if (maps.width === '0px' || maps.width === '0%' || maps.height === '0%' || maps.height === '0px') {
92
+ maps.svgObject.setAttribute('height', '0');
93
+ maps.svgObject.setAttribute('width', '0');
94
+ }
95
+ }
96
+ /**
97
+ * Method to get the mouse position
98
+ *
99
+ * @param {number} pageX - Specifies the pageX.
100
+ * @param {number} pageY - Specifies the pageY.
101
+ * @param {Element} element - Specifies the element.
102
+ * @returns {MapLocation} - Returns the location.
103
+ */
104
+ export function getMousePosition(pageX: number, pageY: number, element: Element): MapLocation {
105
+ const elementRect: ClientRect = element.getBoundingClientRect();
106
+ const pageXOffset: number = element.ownerDocument.defaultView.pageXOffset;
107
+ const pageYOffset: number = element.ownerDocument.defaultView.pageYOffset;
108
+ const clientTop: number = element.ownerDocument.documentElement.clientTop;
109
+ const clientLeft: number = element.ownerDocument.documentElement.clientLeft;
110
+ const positionX: number = elementRect.left + pageXOffset - clientLeft;
111
+ const positionY: number = elementRect.top + pageYOffset - clientTop;
112
+ return new MapLocation((pageX - positionX), (pageY - positionY));
113
+ }
114
+ /**
115
+ * Method to convert degrees to radians
116
+ *
117
+ * @param {number} deg Specifies the degree value
118
+ * @returns {number} Returns the number
119
+ */
120
+ export function degreesToRadians(deg: number): number {
121
+ return deg * (Math.PI / 180);
122
+ }
123
+
124
+ /**
125
+ * Convert radians to degrees method
126
+ *
127
+ * @param {number} radian Specifies the radian value
128
+ * @returns {number} Returns the number
129
+ */
130
+ export function radiansToDegrees(radian: number): number {
131
+ return radian * (180 / Math.PI);
132
+ }
133
+
134
+
135
+ /**
136
+ * Method for converting from latitude and longitude values to points
137
+ *
138
+ * @param {number} latitude - Specifies the latitude.
139
+ * @param {number} longitude - Specifies the longitude.
140
+ * @param {number} factor - Specifies the factor.
141
+ * @param {LayerSettings} layer - Specifies the layer settings.
142
+ * @param {Maps} mapModel - Specifies the maps.
143
+ * @returns {Point} - Returns the point values.
144
+ */
145
+ export function convertGeoToPoint(latitude: number, longitude: number, factor: number, layer: LayerSettings, mapModel: Maps): Point {
146
+ const mapSize: Size = new Size(mapModel.mapAreaRect.width, mapModel.mapAreaRect.height);
147
+ let x: number; let y: number; let value: Point;
148
+ let lat: number; let lng: number; let temp: number;
149
+ const longitudeMinMax: MinMax = mapModel.baseMapBounds.longitude;
150
+ const latitudeMinMax: MinMax = mapModel.baseMapBounds.latitude;
151
+ let latRadian: number = degreesToRadians(latitude);
152
+ const lngRadian: number = degreesToRadians(longitude);
153
+ const type: ProjectionType = mapModel.projectionType;
154
+ const size: number = (mapModel.isTileMap) ? Math.pow(2, 1) * 256 : (isNullOrUndefined(factor)) ?
155
+ Math.min(mapSize.width, mapSize.height) : (Math.min(mapSize.width, mapSize.height) * factor);
156
+ if (layer.geometryType === 'Normal') {
157
+ x = isNullOrUndefined(factor) ? longitude : Math.abs((longitude - longitudeMinMax.min) * factor);
158
+ y = isNullOrUndefined(factor) ? latitude : Math.abs((latitudeMinMax.max - latitude) * factor);
159
+ } else if (layer.geometryType === 'Geographic') {
160
+ switch (type) {
161
+ case 'Mercator': {
162
+ const pixelOrigin: Point = new Point(size / 2, size / 2);
163
+ x = pixelOrigin.x + longitude * (size / 360);
164
+ const sinY: number = calculateBound(Math.sin(degreesToRadians(latitude)), -0.9999, 0.9999);
165
+ y = pixelOrigin.y + 0.5 * (Math.log((1 + sinY) / (1 - sinY))) * (-(size / (2 * Math.PI)));
166
+ break;
167
+ }
168
+ case 'Winkel3':
169
+ value = aitoff(lngRadian, latRadian);
170
+ lng = (value.x + lngRadian / (Math.PI / 2)) / 2;
171
+ lat = (value.y + latRadian) / 2;
172
+ break;
173
+ case 'Miller':
174
+ lng = lngRadian;
175
+ lat = (1.25 * Math.log(Math.tan((Math.PI / 4) + (.4 * latRadian))));
176
+ break;
177
+ case 'Eckert3':
178
+ temp = Math.sqrt(Math.PI * (4 + Math.PI));
179
+ lng = 2 / temp * lngRadian * (1 + Math.sqrt(1 - 4 * latRadian * latRadian / (Math.PI * Math.PI)));
180
+ lat = 4 / temp * latRadian;
181
+ break;
182
+ case 'AitOff':
183
+ value = aitoff(lngRadian, latRadian);
184
+ lng = value.x;
185
+ lat = value.y;
186
+ break;
187
+ case 'Eckert5':
188
+ lng = lngRadian * (1 + Math.cos(latRadian)) / Math.sqrt(2 + Math.PI);
189
+ lat = 2 * latRadian / Math.sqrt(2 + Math.PI);
190
+ break;
191
+ case 'Equirectangular':
192
+ lng = lngRadian;
193
+ lat = latRadian;
194
+ break;
195
+ case 'Eckert6': {
196
+ const epsilon: number = 1e-6;
197
+ temp = (1 + (Math.PI / 2)) * Math.sin(latRadian);
198
+ let delta: number = Infinity;
199
+ for (let i: number = 0; i < 10 && Math.abs(delta) > epsilon; i++) {
200
+ delta = (latRadian + (Math.sin(latRadian)) - temp) / (1 + Math.cos(latRadian));
201
+ latRadian = latRadian - delta;
202
+ }
203
+ temp = Math.sqrt(2 + Math.PI);
204
+ lng = lngRadian * (1 + Math.cos(latRadian)) / temp;
205
+ lat = 2 * latRadian / temp;
206
+ break;
207
+ }
208
+ }
209
+ x = (type === 'Mercator') ? x : roundTo(xToCoordinate(mapModel, radiansToDegrees(lng)), 3);
210
+ y = (type === 'Mercator') ? y : (-(roundTo(yToCoordinate(mapModel, radiansToDegrees(lat)), 3)));
211
+ }
212
+ return new Point(x, y);
213
+ }
214
+ /**
215
+ * Converting tile latitude and longitude to point
216
+ *
217
+ * @param {MapLocation} center Specifies the map center location
218
+ * @param {number} zoomLevel Specifies the zoom level
219
+ * @param {MapLocation} tileTranslatePoint Specifies the tile translate point
220
+ * @param {boolean} isMapCoordinates Specifies the boolean value
221
+ * @returns {MapLocation} Returns the location value
222
+ */
223
+ export function convertTileLatLongToPoint(
224
+ center: MapLocation, zoomLevel: number, tileTranslatePoint: MapLocation, isMapCoordinates: boolean): MapLocation {
225
+ const size: number = Math.pow(2, zoomLevel) * 256;
226
+ const x: number = (center.x + 180) / 360;
227
+ const sinLatitude: number = Math.sin(center.y * Math.PI / 180);
228
+ const y: number = 0.5 - Math.log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * Math.PI);
229
+ let pixelX: number = center.x;
230
+ let pixelY: number = center.y;
231
+ if (isMapCoordinates) {
232
+ pixelX = (x * size + 0.5) + tileTranslatePoint.x;
233
+ pixelY = (y * size + 0.5) + tileTranslatePoint.y;
234
+ }
235
+ return { x: pixelX, y: pixelY };
236
+ }
237
+ /**
238
+ * Method for calculate x point
239
+ *
240
+ * @param {Maps} mapObject - Specifies the maps.
241
+ * @param {number} val - Specifies the value.
242
+ * @returns {number} - Returns the number.
243
+ */
244
+ export function xToCoordinate(mapObject: Maps, val: number): number {
245
+ const longitudeMinMax: MinMax = mapObject.baseMapBounds.longitude;
246
+ const totalSize: number = isNullOrUndefined(mapObject.baseSize) ? mapObject.mapAreaRect.width : mapObject.mapAreaRect.width +
247
+ (Math.abs(mapObject.baseSize.width - mapObject.mapAreaRect.width) / 2);
248
+ return Math.round(totalSize * (val - longitudeMinMax.min) / (longitudeMinMax.max - longitudeMinMax.min) * 100) / 100;
249
+ }
250
+
251
+ /**
252
+ * Method for calculate y point
253
+ *
254
+ * @param {Maps} mapObject - Specifies the maps.
255
+ * @param {number} val - Specifies the value.
256
+ * @returns {number} - Returns the number.
257
+ */
258
+ export function yToCoordinate(mapObject: Maps, val: number): number {
259
+ const latitudeMinMax: MinMax = mapObject.baseMapBounds.latitude;
260
+ return Math.round(mapObject.mapAreaRect.height * (val - latitudeMinMax.min) / (latitudeMinMax.max - latitudeMinMax.min) * 100) / 100;
261
+ }
262
+
263
+ /**
264
+ * Method for calculate aitoff projection
265
+ *
266
+ * @param {number} x - Specifies the x value.
267
+ * @param {number} y - Specifies the y value.
268
+ * @returns {Point} - Returns the point value.
269
+ */
270
+ export function aitoff(x: number, y: number): Point {
271
+ const cosy: number = Math.cos(y);
272
+ const sincia: number = sinci(acos(cosy * Math.cos(x /= 2)));
273
+ return new Point(2 * cosy * Math.sin(x) * sincia, Math.sin(y) * sincia);
274
+ }
275
+
276
+
277
+ /**
278
+ * Method to round the number
279
+ *
280
+ * @param {number} a - Specifies the a value
281
+ * @param {number} b - Specifies the b value
282
+ * @returns {number} - Returns the number
283
+ */
284
+ export function roundTo(a: number, b: number): number {
285
+ const c: number = Math.pow(10, b);
286
+ return (Math.round(a * c) / c);
287
+ }
288
+
289
+ /**
290
+ *
291
+ * @param {number} x - Specifies the x value
292
+ * @returns {number} - Returns the number
293
+ */
294
+ export function sinci(x: number): number {
295
+ return x / Math.sin(x);
296
+ }
297
+
298
+ /**
299
+ *
300
+ * @param {number} a - Specifies the a value
301
+ * @returns {number} - Returns the number
302
+ */
303
+ export function acos(a: number): number {
304
+ return Math.acos(a);
305
+ }
306
+
307
+ /**
308
+ * Method to calculate bound
309
+ *
310
+ * @param {number} value Specifies the value
311
+ * @param {number} min Specifies the minimum value
312
+ * @param {number} max Specifies the maximum value
313
+ * @returns {number} Returns the value
314
+ */
315
+ export function calculateBound(value: number, min: number, max: number): number {
316
+ if (!isNullOrUndefined(min)) {
317
+ value = Math.max(value, min);
318
+ }
319
+ if (!(isNullOrUndefined(max))) {
320
+ value = Math.min(value, max);
321
+ }
322
+ return value;
323
+ }
324
+
325
+ /**
326
+ * To trigger the download element
327
+ *
328
+ * @param {string} fileName Specifies the file name
329
+ * @param {ExportType} type Specifies the type
330
+ * @param {string} url Specifies the url
331
+ * @param {boolean} isDownload Specifies whether download a file.
332
+ * @returns {void}
333
+ */
334
+ export function triggerDownload(fileName: string, type: ExportType, url: string, isDownload: boolean): void {
335
+ createElement('a', {
336
+ attrs: {
337
+ 'download': fileName + '.' + (type as string).toLocaleLowerCase(),
338
+ 'href': url
339
+ }
340
+ }).dispatchEvent(new MouseEvent(isDownload ? 'click' : 'move', {
341
+ view: window,
342
+ bubbles: false,
343
+ cancelable: true
344
+ }));
345
+ }
346
+ /**
347
+ * Map internal class for point
348
+ */
349
+
350
+ export class Point {
351
+ /**
352
+ * Point x value
353
+ */
354
+ public x: number;
355
+ /**
356
+ * Point Y value
357
+ */
358
+ public y: number;
359
+ constructor(x: number, y: number) {
360
+ this.x = x;
361
+ this.y = y;
362
+ }
363
+ }
364
+
365
+ /**
366
+ * Map internal class for min and max
367
+ *
368
+ */
369
+
370
+ export class MinMax {
371
+ public min: number;
372
+ public max: number;
373
+ constructor(min: number, max: number) {
374
+ this.min = min;
375
+ this.max = max;
376
+ }
377
+ }
378
+
379
+ /**
380
+ * Map internal class locations
381
+ */
382
+
383
+ export class GeoLocation {
384
+ public latitude: MinMax;
385
+ public longitude: MinMax;
386
+ constructor(latitude: MinMax, longitude: MinMax) {
387
+ this.latitude = new MinMax(latitude.min, latitude.max);
388
+ this.longitude = new MinMax(longitude.min, longitude.max);
389
+ }
390
+ }
391
+
392
+ /**
393
+ * Function to measure the height and width of the text.
394
+ *
395
+ * @param {string} text Specifies the text
396
+ * @param {FontModel} font Specifies the font
397
+ * @returns {Size} Returns the size
398
+ * @private
399
+ */
400
+ export function measureText(text: string, font: FontModel): Size {
401
+ let measureObject: HTMLElement = document.getElementById('mapsmeasuretext');
402
+
403
+ if (measureObject === null) {
404
+ measureObject = createElement('text', { id: 'mapsmeasuretext' });
405
+ document.body.appendChild(measureObject);
406
+ }
407
+ measureObject.innerHTML = text;
408
+ measureObject.style.position = 'absolute';
409
+ if (typeof (font.size) === 'number') {
410
+ measureObject.style.fontSize = (font.size) + 'px';
411
+ } else {
412
+ measureObject.style.fontSize = font.size;
413
+ }
414
+ measureObject.style.fontWeight = font.fontWeight;
415
+ measureObject.style.fontStyle = font.fontStyle;
416
+ measureObject.style.fontFamily = font.fontFamily;
417
+ measureObject.style.visibility = 'hidden';
418
+ measureObject.style.top = '-100';
419
+ measureObject.style.left = '0';
420
+ measureObject.style.whiteSpace = 'nowrap';
421
+ // For bootstrap line height issue
422
+ measureObject.style.lineHeight = 'normal';
423
+ return new Size(measureObject.clientWidth, measureObject.clientHeight);
424
+ }
425
+
426
+ /**
427
+ * Internal use of text options
428
+ *
429
+ * @private
430
+ */
431
+ export class TextOption {
432
+ public anchor: string;
433
+ public id: string;
434
+ public transform: string = '';
435
+ public x: number;
436
+ public y: number;
437
+ public text: string | string[];
438
+ public baseLine: string = 'auto';
439
+
440
+ constructor(id?: string, x?: number, y?: number, anchor?: string, text?: string | string[], transform: string = '', baseLine?: string) {
441
+ this.id = id;
442
+ this.text = text;
443
+ this.transform = transform;
444
+ this.anchor = anchor;
445
+ this.x = x;
446
+ this.y = y;
447
+ this.baseLine = baseLine;
448
+ }
449
+ }
450
+ /**
451
+ * Internal use of path options
452
+ *
453
+ * @private
454
+ */
455
+ export class PathOption {
456
+ public id: string;
457
+ public fill: string;
458
+ public stroke: string;
459
+ public ['stroke-width']: number;
460
+ public ['stroke-dasharray']: string;
461
+ public ['stroke-opacity']: number;
462
+ public ['fill-opacity']: number;
463
+ public d: string;
464
+ constructor(
465
+ id: string, fill: string, width: number, color: string, fillOpacity?: number, strokeOpacity?: number,
466
+ dashArray?: string, d?: string
467
+ ) {
468
+ this.id = id;
469
+ this['fill-opacity'] = fillOpacity;
470
+ this['stroke-opacity'] = strokeOpacity;
471
+ this.fill = fill;
472
+ this.stroke = color;
473
+ this['stroke-width'] = width;
474
+ this['stroke-dasharray'] = dashArray;
475
+ this.d = d;
476
+ }
477
+ }
478
+ /** @private */
479
+ export class ColorValue {
480
+ public r: number;
481
+ public g: number;
482
+ public b: number;
483
+ constructor(r?: number, g?: number, b?: number) {
484
+ this.r = r;
485
+ this.g = g;
486
+ this.b = b;
487
+ }
488
+ }
489
+ /**
490
+ * Internal use of rectangle options
491
+ *
492
+ * @private
493
+ */
494
+ export class RectOption extends PathOption {
495
+
496
+ public x: number;
497
+ public y: number;
498
+ public height: number;
499
+ public width: number;
500
+ public rx: number;
501
+ public ry: number;
502
+ public transform: string;
503
+ public ['stroke-dasharray']: string;
504
+ constructor(
505
+ id: string, fill: string, border: BorderModel, fillOpacity: number,
506
+ rect: Rect, rx?: number, ry?: number, transform?: string, dashArray?: string
507
+ ) {
508
+ super(id, fill, border.width, border.color, fillOpacity, border.opacity);
509
+ this.y = rect.y;
510
+ this.x = rect.x;
511
+ this.height = rect.height;
512
+ this.width = rect.width;
513
+ this.rx = rx ? rx : 0;
514
+ this.ry = ry ? ry : 0;
515
+ this.transform = transform ? transform : '';
516
+ this['stroke-dasharray'] = dashArray;
517
+ this['fill-opacity'] = fillOpacity;
518
+ this['stroke-opacity'] = border.opacity;
519
+ }
520
+ }
521
+ /**
522
+ * Internal use of circle options
523
+ *
524
+ * @private
525
+ */
526
+ export class CircleOption extends PathOption {
527
+ public cy: number;
528
+ public cx: number;
529
+ public r: number;
530
+ public ['stroke-dasharray']: string;
531
+ constructor(id: string, fill: string, border: BorderModel, fillOpacity: number,
532
+ cx: number, cy: number, r: number, dashArray: string) {
533
+ super(id, fill, border.width, border.color, fillOpacity, border.opacity, dashArray);
534
+ this.cy = cy;
535
+ this.cx = cx;
536
+ this.r = r;
537
+ this['stroke-dasharray'] = dashArray;
538
+ this['fill-opacity'] = fillOpacity;
539
+ this['stroke-opacity'] = border.opacity;
540
+ }
541
+ }
542
+
543
+ /**
544
+ * Internal use of polygon options
545
+ *
546
+ * @private
547
+ */
548
+ export class PolygonOption extends PathOption {
549
+ public points: string;
550
+ constructor(id: string, points: string, fill: string, width: number, color: string, fillOpacity: number = 1,
551
+ strokeOpacity: number = 1, dashArray: string = ''
552
+ ) {
553
+ super(id, fill, width, color, fillOpacity, strokeOpacity, dashArray);
554
+ this.points = points;
555
+ }
556
+ }
557
+ /**
558
+ * Internal use of polyline options
559
+ *
560
+ * @private
561
+ */
562
+ export class PolylineOption extends PolygonOption {
563
+ constructor(id: string, points: string, fill: string, width: number, color: string,
564
+ fillOpacity: number = 1, strokeOpacity: number = 1, dashArray: string = '') {
565
+ super(id, points, fill, width, color, fillOpacity, strokeOpacity, dashArray);
566
+ }
567
+ }
568
+ /**
569
+ * Internal use of line options
570
+ *
571
+ * @private
572
+ */
573
+ export class LineOption extends PathOption {
574
+ public x1: number;
575
+ public y1: number;
576
+ public x2: number;
577
+ public y2: number;
578
+ constructor(id: string, line: Line, fill: string, width: number, color: string,
579
+ fillOpacity: number = 1, strokeOpacity: number = 1, dashArray: string = ''
580
+ ) {
581
+ super(id, fill, width, color, fillOpacity, strokeOpacity, dashArray);
582
+ this.x1 = line.x1;
583
+ this.y1 = line.y1;
584
+ this.x2 = line.x2;
585
+ this.y2 = line.y2;
586
+ }
587
+ }
588
+ /**
589
+ * Internal use of line
590
+ *
591
+ * @property {number} Line - Specifies the line class
592
+ */
593
+ export class Line {
594
+ public x1: number;
595
+ public y1: number;
596
+ public x2: number;
597
+ public y2: number;
598
+ constructor(x1: number, y1: number, x2: number, y2: number) {
599
+ this.x1 = x1;
600
+ this.y1 = y1;
601
+ this.x2 = x2;
602
+ this.y2 = y2;
603
+ }
604
+ }
605
+ /**
606
+ * Internal use of map location type
607
+ *
608
+ */
609
+ export class MapLocation {
610
+ /**
611
+ * To specify x value
612
+ */
613
+ public x: number;
614
+ /**
615
+ * To specify y value
616
+ */
617
+ public y: number;
618
+ constructor(x: number, y: number) {
619
+ this.x = x;
620
+ this.y = y;
621
+ }
622
+ }
623
+ /**
624
+ * Internal use of type rect
625
+ *
626
+ * @private
627
+ */
628
+ export class Rect {
629
+
630
+ public x: number;
631
+ public y: number;
632
+ public height: number;
633
+ public width: number;
634
+
635
+ constructor(x: number, y: number, width: number, height: number) {
636
+ this.x = x;
637
+ this.y = y;
638
+ this.width = width;
639
+ this.height = height;
640
+ }
641
+ }
642
+ /**
643
+ * Defines the pattern unit types for drawing the patterns in maps.
644
+ */
645
+ export type patternUnits =
646
+ /** Specifies the user space for maps. */
647
+ 'userSpaceOnUse' |
648
+ /** Specifies the bounding box for the object. */
649
+ 'objectBoundingBox';
650
+ /**
651
+ * Internal use for pattern creation.
652
+ *
653
+ * @property {PatternOptions} PatternOptions - Specifies the pattern option class.
654
+ */
655
+ export class PatternOptions {
656
+ public id: string;
657
+ public patternUnits: patternUnits;
658
+ public patternContentUnits: patternUnits;
659
+ public patternTransform: string;
660
+ public x: number;
661
+ public y: number;
662
+ public width: number;
663
+ public height: number;
664
+ public href: string;
665
+ constructor(
666
+ id: string, x: number, y: number, width: number, height: number, patternUnits: patternUnits = 'userSpaceOnUse',
667
+ patternContentUnits: patternUnits = 'userSpaceOnUse', patternTransform: string = '', href: string = '') {
668
+ this.id = id;
669
+ this.x = x;
670
+ this.y = y;
671
+ this.width = width;
672
+ this.height = height;
673
+ this.patternUnits = patternUnits;
674
+ this.patternContentUnits = patternContentUnits;
675
+ this.patternTransform = patternTransform;
676
+ this.href = href;
677
+ }
678
+ }
679
+ /**
680
+ * Internal rendering of text
681
+ *
682
+ * @param {TextOption} option Specifies the text option
683
+ * @param {FontModel} style Specifies the style
684
+ * @param {string} color Specifies the color
685
+ * @param {HTMLElement | Element} parent Specifies the parent element
686
+ * @param {boolean} isMinus Specifies the boolean value
687
+ * @returns {Element} Returns the html object
688
+ * @private
689
+ */
690
+ export function renderTextElement(
691
+ option: TextOption, style: FontModel, color: string, parent: HTMLElement | Element, isMinus: boolean = false
692
+ ): Element {
693
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
694
+ const renderOptions: any = {
695
+ 'id': option.id,
696
+ 'x': option.x,
697
+ 'y': option.y,
698
+ 'fill': color,
699
+ 'font-size': style.size,
700
+ 'font-style': style.fontStyle,
701
+ 'font-family': style.fontFamily,
702
+ 'font-weight': style.fontWeight,
703
+ 'text-anchor': option.anchor,
704
+ 'transform': option.transform,
705
+ 'opacity': style.opacity,
706
+ 'dominant-baseline': option.baseLine
707
+ };
708
+ const text: string = typeof option.text === 'string' || typeof option.text === 'number' ? option.text : isMinus ? option.text[option.text.length - 1] : option.text[0];
709
+ let tspanElement: Element;
710
+ const renderer: SvgRenderer = new SvgRenderer('');
711
+ let height: number;
712
+ const htmlObject: HTMLElement = <HTMLElement>renderer.createText(renderOptions, text);
713
+ htmlObject.style['user-select'] = 'none';
714
+ htmlObject.style['font-family'] = style.fontFamily;
715
+ htmlObject.style['font-size'] = style.size;
716
+ htmlObject.style['font-weight'] = style.fontWeight;
717
+ htmlObject.style['font-color'] = style.color;
718
+ htmlObject.style['-moz-user-select'] = 'none';
719
+ htmlObject.style['-webkit-touch-callout'] = 'none';
720
+ htmlObject.style['-webkit-user-select'] = 'none';
721
+ htmlObject.style['-khtml-user-select'] = 'none';
722
+ htmlObject.style['-ms-user-select'] = 'none';
723
+ htmlObject.style['-o-user-select'] = 'none';
724
+ if (typeof option.text !== 'string' && option.text.length > 1) {
725
+ for (let i: number = 1, len: number = option.text.length; i < len; i++) {
726
+ height = (measureText(option.text[i], style).height);
727
+ tspanElement = renderer.createTSpan(
728
+ {
729
+ 'x': option.x, 'id': option.id,
730
+ 'y': (option.y) + ((isMinus) ? -(i * height) : (i * height))
731
+ },
732
+ isMinus ? option.text[option.text.length - (i + 1)] : option.text[i]
733
+ );
734
+ htmlObject.appendChild(tspanElement);
735
+ }
736
+ }
737
+ parent.appendChild(htmlObject);
738
+ return htmlObject;
739
+ }
740
+
741
+ /**
742
+ * @param {HTMLCollection} element Specifies the html collection
743
+ * @param {string} markerId Specifies the marker id
744
+ * @param {any} data Specifies the data
745
+ * @param {number} index Specifies the index
746
+ * @param {Maps} mapObj Specifies the map object
747
+ * @returns {HTMLCollection} Returns the html collection
748
+ * @private
749
+ */
750
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
751
+ export function convertElement(element: HTMLCollection, markerId: string, data: any, index: number, mapObj: Maps): HTMLElement {
752
+ const childElement: HTMLElement = createElement('div', {
753
+ id: markerId,
754
+ styles: 'position: absolute;pointer-events: auto;'
755
+ });
756
+ let elementLength: number = element.length;
757
+ while (elementLength > 0) {
758
+ childElement.appendChild(element[0]);
759
+ elementLength--;
760
+ }
761
+ let templateHtml: string = childElement.innerHTML;
762
+ let templateSplitValue: string;
763
+ const properties: string[] = Object.keys(data);
764
+ for (let i: number = 0; i < properties.length; i++) {
765
+ if (typeof data[properties[i]] === 'object') {
766
+ templateHtml = convertStringToValue(templateHtml, '', data, mapObj);
767
+ // eslint-disable-next-line @typescript-eslint/ban-types
768
+ } else if ((<String>properties[i]).toLowerCase() !== 'latitude' && (<string>properties[i]).toLowerCase() !== 'longitude') {
769
+ templateHtml = templateHtml.replace(new RegExp('{{:' + <string>properties[i] + '}}', 'g'), data[properties[i].toString()]);
770
+ }
771
+ }
772
+ childElement.innerHTML = templateHtml;
773
+ return childElement;
774
+ }
775
+
776
+ /**
777
+ *
778
+ * @param {string} value - Specifies the value
779
+ * @param {Maps} maps - Specifies the instance of the maps
780
+ * @returns {string} - Returns the string value
781
+ */
782
+ export function formatValue(value: string, maps: Maps): string {
783
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
784
+ let formatValue: string; let formatFunction: any;
785
+ if (maps.format && !isNaN(Number(value))) {
786
+ formatFunction = maps.intl.getNumberFormat(
787
+ { format: maps.format, useGrouping: maps.useGroupingSeparator });
788
+ formatValue = formatFunction(Number(value));
789
+ } else {
790
+ formatValue = value;
791
+ }
792
+ return formatValue;
793
+ }
794
+
795
+ /**
796
+ *
797
+ * @param {string} stringTemplate - Specifies the template
798
+ * @param {string} format - Specifies the format
799
+ * @param {any} data - Specifies the data
800
+ * @param {Maps} maps - Specifies the instance of the maps
801
+ * @returns {string} - Returns the string value
802
+ */
803
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
804
+ export function convertStringToValue(stringTemplate: string, format: string, data: any, maps: Maps): string {
805
+ let templateHtml: string = (stringTemplate === '') ? format : stringTemplate;
806
+ const templateValue: string[] = (stringTemplate === '') ? templateHtml.split('${') : templateHtml.split('{{:');
807
+ for (let i: number = 0; i < templateValue.length; i++) {
808
+ if ((templateValue[i].indexOf('}}') > -1 && templateValue[i].indexOf('.') > -1) ||
809
+ (templateValue[i].indexOf('}') > -1 && templateValue[i].search('.') > -1)) {
810
+ const split: string[] = (stringTemplate === '') ? templateValue[i].split('}') : templateValue[i].split('}}');
811
+ for (let j: number = 0; j < split.length; j++) {
812
+ if (split[j].indexOf('.') > -1) {
813
+ const templateSplitValue: string = (getValueFromObject(data, split[j])).toString();
814
+ templateHtml = (stringTemplate === '') ?
815
+ templateHtml.split('${' + split[j] + '}').join(formatValue(templateSplitValue, maps)) :
816
+ templateHtml.replace(new RegExp('{{:' + split[j] + '}}', 'g'), templateSplitValue);
817
+ }
818
+ }
819
+ }
820
+ }
821
+ return templateHtml;
822
+ }
823
+
824
+ /**
825
+ *
826
+ * @param {Element} element - Specifies the element
827
+ * @param {string} labelId - Specifies the label id
828
+ * @param {any} data - Specifies the data
829
+ * @param {number} index - Specifies the index
830
+ * @param {Maps} mapObj - Specifies the map object
831
+ * @returns {HTMLElement} - Returns the html element
832
+ */
833
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
834
+ export function convertElementFromLabel(element: Element, labelId: string, data: any, index: number, mapObj: Maps): HTMLElement {
835
+ const labelEle: Element = isNullOrUndefined(element.childElementCount) ? element[0] : element;
836
+ let templateHtml: string = labelEle.outerHTML;
837
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
838
+ const properties: any[] = Object.keys(data);
839
+ for (let i: number = 0; i < properties.length; i++) {
840
+ // eslint-disable-next-line @typescript-eslint/ban-types
841
+ templateHtml = templateHtml.replace(new RegExp('{{:' + <String>properties[i] + '}}', 'g'), data[properties[i].toString()]);
842
+ }
843
+ return createElement('div', {
844
+ id: labelId,
845
+ innerHTML: templateHtml,
846
+ styles: 'position: absolute'
847
+ });
848
+ }
849
+
850
+ /**
851
+ *
852
+ * @param {MarkerType} shape - Specifies the shape
853
+ * @param {string} imageUrl - Specifies the image url
854
+ * @param {Point} location - Specifies the location
855
+ * @param {string} markerID - Specifies the marker id
856
+ * @param {any} shapeCustom - Specifies the shape custom
857
+ * @param {Element} markerCollection - Specifies the marker collection
858
+ * @param {Maps} maps - Specifies the instance of the maps
859
+ * @returns {Element} - Returns the element
860
+ */
861
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
862
+ export function drawSymbols(shape: MarkerType, imageUrl: string, location: Point, markerID: string, shapeCustom: any, markerCollection: Element, maps: Maps): Element {
863
+ let markerEle: Element; let x: number; let y: number;
864
+ const size: Size = <Size>shapeCustom['size'];
865
+ const borderColor: string = shapeCustom['borderColor'];
866
+ const borderWidth: number = parseFloat(shapeCustom['borderWidth']);
867
+ const borderOpacity: number = parseFloat(shapeCustom['borderOpacity']);
868
+ const fill: string = shapeCustom['fill'];
869
+ const dashArray: string = shapeCustom['dashArray'];
870
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
871
+ const border: any = { color: borderColor, width: borderWidth, opacity: borderOpacity };
872
+ const opacity: number = shapeCustom['opacity']; const padding: number = 5;
873
+ let rectOptions: RectOption;
874
+ const pathOptions: PathOption = new PathOption(markerID, fill, borderWidth, borderColor, opacity, borderOpacity, dashArray, '');
875
+ size.width = typeof(size.width) === 'string' ? parseInt(size.width, 10) : size.width;
876
+ size.height = typeof(size.height) === 'string' ? parseInt(size.height, 10) : size.height;
877
+ if (shape === 'Circle') {
878
+ const radius: number = (size.width + size.height) / 4;
879
+ const circleOptions: CircleOption = new CircleOption(markerID, fill, border, opacity,
880
+ location.x, location.y, radius, dashArray);
881
+ markerEle = maps.renderer.drawCircle(circleOptions) as SVGCircleElement;
882
+ } else if (shape === 'Rectangle') {
883
+ x = location.x - (size.width / 2);
884
+ y = location.y - (size.height / 2);
885
+ rectOptions = new RectOption(
886
+ markerID, fill, border, opacity, new Rect(x, y, size.width, size.height), null, null, '', dashArray
887
+ );
888
+ markerEle = maps.renderer.drawRectangle(rectOptions) as SVGRectElement;
889
+ } else if (shape === 'Image') {
890
+ x = location.x - (size.width / 2);
891
+ y = location.y - size.height;
892
+ merge(pathOptions, { 'href': imageUrl, 'height': size.height, 'width': size.width, x: x, y: y });
893
+ markerEle = maps.renderer.drawImage(pathOptions) as SVGImageElement;
894
+ } else {
895
+ markerEle = calculateShapes(maps, shape, pathOptions, size, location, markerCollection);
896
+ }
897
+ return markerEle;
898
+ }
899
+
900
+ /**
901
+ *
902
+ * @param {any} data - Specifies the data
903
+ * @param {string} value - Specifies the value
904
+ * @returns {any} - Returns the data
905
+ */
906
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
907
+ export function getValueFromObject(data: any, value: string): any {
908
+ if (!isNullOrUndefined(data) && !isNullOrUndefined(value)) {
909
+ const splits: string[] = value.replace(/\[/g, '.').replace(/\]/g, '').split('.');
910
+ if (splits.length === 1) {
911
+ data = data[splits[0]];
912
+ }
913
+ else {
914
+ for (let i: number = 0; i < splits.length && !isNullOrUndefined(data); i++) {
915
+ data = data[splits[i]];
916
+ }
917
+ }
918
+ }
919
+ return data;
920
+ }
921
+
922
+ /**
923
+ *
924
+ * @param {IMarkerRenderingEventArgs} eventArgs - Specifies the event arguments
925
+ * @param {any} data - Specifies the data
926
+ * @returns {IMarkerRenderingEventArgs} - Returns the arguments
927
+ */
928
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
929
+ export function markerColorChoose(eventArgs: IMarkerRenderingEventArgs, data: any): IMarkerRenderingEventArgs {
930
+ const color: string = (!isNullOrUndefined(eventArgs.colorValuePath)) ? ((eventArgs.colorValuePath.indexOf('.') > -1) ? (getValueFromObject(data, eventArgs.colorValuePath)).toString() :
931
+ data[eventArgs.colorValuePath]) : data[eventArgs.colorValuePath];
932
+ eventArgs.fill = (!isNullOrUndefined(eventArgs.colorValuePath) &&
933
+ !isNullOrUndefined(color)) ?
934
+ ((eventArgs.colorValuePath.indexOf('.') > -1) ? (getValueFromObject(data, eventArgs.colorValuePath)).toString() :
935
+ data[eventArgs.colorValuePath]) : eventArgs.fill;
936
+ return eventArgs;
937
+ }
938
+
939
+ /**
940
+ *
941
+ * @param {IMarkerRenderingEventArgs} eventArgs - Specifies the event arguments
942
+ * @param {any} data - Specifies the data
943
+ * @returns {IMarkerRenderingEventArgs} - Returns the arguments
944
+ */
945
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
946
+ export function markerShapeChoose(eventArgs: IMarkerRenderingEventArgs, data: any): IMarkerRenderingEventArgs {
947
+ if (!isNullOrUndefined(eventArgs.shapeValuePath) && !isNullOrUndefined(data[eventArgs.shapeValuePath])) {
948
+ const shape: MarkerType = ((eventArgs.shapeValuePath.indexOf('.') > -1) ?
949
+ (getValueFromObject(data, eventArgs.shapeValuePath).toString()) as MarkerType :
950
+ data[eventArgs.shapeValuePath]);
951
+ eventArgs.shape = (shape.toString() !== "") ? shape : eventArgs.shape;
952
+ if (data[eventArgs.shapeValuePath] === 'Image') {
953
+ eventArgs.imageUrl = (!isNullOrUndefined(eventArgs.imageUrlValuePath)) ?
954
+ ((eventArgs.imageUrlValuePath.indexOf('.') > -1) ? getValueFromObject(data, eventArgs.imageUrlValuePath).toString() : (!isNullOrUndefined(data[eventArgs.imageUrlValuePath]) ?
955
+ data[eventArgs.imageUrlValuePath] : eventArgs.imageUrl)) : eventArgs.imageUrl;
956
+ }
957
+ }
958
+ else {
959
+ const shapes: MarkerType = (!isNullOrUndefined(eventArgs.shapeValuePath)) ? ((eventArgs.shapeValuePath.indexOf('.') > -1) ? (getValueFromObject(data, eventArgs.shapeValuePath).toString() as MarkerType) : eventArgs.shape) : eventArgs.shape;
960
+ eventArgs.shape = (shapes.toString() !== "") ? shapes : eventArgs.shape;
961
+ const shapeImage: string = (!isNullOrUndefined(eventArgs.imageUrlValuePath)) ?
962
+ ((eventArgs.imageUrlValuePath.indexOf('.') > -1) ? getValueFromObject(data, eventArgs.imageUrlValuePath).toString() as MarkerType : (!isNullOrUndefined(data[eventArgs.imageUrlValuePath]) ?
963
+ data[eventArgs.imageUrlValuePath] : eventArgs.imageUrl)) : eventArgs.imageUrl;
964
+ eventArgs.imageUrl = shapeImage;
965
+ }
966
+ return eventArgs;
967
+ }
968
+
969
+ /**
970
+ *
971
+ * @param {LayerSettings} currentLayer - Specifies the current layer
972
+ * @param {HTMLElement | Element} markerTemplate - Specifies the marker template
973
+ * @param {Maps} maps - Specifies the instance of the maps
974
+ * @param {number} layerIndex - Specifies the layer index
975
+ * @param {Element} markerCollection - Specifies the marker collection
976
+ * @param {Element} layerElement - Specifies the layer element
977
+ * @param {boolean} check - Specifies the boolean value
978
+ * @param {boolean} zoomCheck - Specifies the boolean value
979
+ * @returns {void}
980
+ */
981
+ export function clusterTemplate(currentLayer: LayerSettings, markerTemplate: HTMLElement | Element, maps: Maps, layerIndex: number, markerCollection: Element,
982
+ layerElement: Element, check: boolean, zoomCheck: boolean): void {
983
+ let bounds1: DOMRect;
984
+ let bounds2: DOMRect;
985
+ let colloideBounds: DOMRect[] = [];
986
+ let clusterColloideBounds: Element[] = [];
987
+ let tempX: number = 0;
988
+ let tempY: number = 0;
989
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
990
+ let data: any;
991
+ const style: FontModel = currentLayer.markerClusterSettings.labelStyle;
992
+ let options: TextOption;
993
+ let textElement: Element;
994
+ let tempElement1: Element;
995
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
996
+ let shapeCustom: any;
997
+ let tempElement: Element;
998
+ const postionY: number = (15 / 4);
999
+ let m: number = 0;
1000
+ let indexCollection: number[] = [];
1001
+ const clusters: MarkerClusterSettingsModel = currentLayer.markerClusterSettings;
1002
+ const clusterGroup: Element = maps.renderer.createGroup({ id: maps.element.id + '_LayerIndex_' + layerIndex + '_markerCluster' });
1003
+ const eventArg: IMarkerClusterRenderingEventArgs = {
1004
+ cancel: false, name: markerClusterRendering, fill: clusters.fill, height: clusters.height,
1005
+ width: clusters.width, imageUrl: clusters.imageUrl, shape: clusters.shape,
1006
+ data: data, maps: maps, cluster: clusters, border: clusters.border
1007
+ };
1008
+ maps.trigger('markerClusterRendering', eventArg, (clusterargs: IMarkerClusterRenderingEventArgs) => {
1009
+ for (let o: number = 0; o < markerTemplate.childElementCount; o++) {
1010
+ indexCollection = [];
1011
+ if (markerTemplate.childNodes[o]['style']['visibility'] !== 'hidden') {
1012
+ tempElement = markerTemplate.childNodes[o] as Element;
1013
+ bounds1 = tempElement.getBoundingClientRect() as DOMRect;
1014
+ indexCollection.push(o as number);
1015
+ if (!isNullOrUndefined(bounds1)) {
1016
+ for (let p: number = o + 1; p < markerTemplate.childElementCount; p++) {
1017
+ if (markerTemplate.childNodes[p]['style']['visibility'] !== 'hidden') {
1018
+ tempElement = markerTemplate.childNodes[p] as Element;
1019
+ bounds2 = tempElement.getBoundingClientRect() as DOMRect;
1020
+ if (!isNullOrUndefined(bounds2)) {
1021
+ if (!(bounds1.left > bounds2.right || bounds1.right < bounds2.left
1022
+ || bounds1.top > bounds2.bottom || bounds1.bottom < bounds2.top)) {
1023
+ colloideBounds.push(bounds2);
1024
+ markerTemplate.childNodes[p]['style']['visibility'] = 'hidden';
1025
+ indexCollection.push(p as number);
1026
+ }
1027
+ }
1028
+ }
1029
+ }
1030
+ tempX = bounds1.left + bounds1.width / 2;
1031
+ tempY = bounds1.top + bounds1.height;
1032
+ if (colloideBounds.length > 0) {
1033
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1034
+ indexCollection = indexCollection.filter((item: any, index: any, value: any) => value.indexOf(item) === index);
1035
+ const container: ClientRect = maps.element.getBoundingClientRect();
1036
+ tempX = tempX - container['left'];
1037
+ tempY = (tempY - ((maps.availableSize.height <= container['height']) ?
1038
+ container['top'] : (container['bottom'] - container['top'])));
1039
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1040
+ const translate: any = (maps.isTileMap) ? new Object() : getTranslate(maps, currentLayer, false);
1041
+ const transPoint: Point = (maps.isTileMap) ? { x: 0, y: 0 } : (maps.translatePoint.x !== 0) ?
1042
+ maps.translatePoint : translate['location'];
1043
+ const dataIndex: number = parseInt(markerTemplate.childNodes[o]['id'].split('_dataIndex_')[1].split('_')[0], 10);
1044
+ const markerIndex: number = parseInt(markerTemplate.childNodes[o]['id'].split('_MarkerIndex_')[1].split('_')[0], 10);
1045
+ const markerSetting: MarkerSettingsModel = currentLayer.markerSettings[markerIndex];
1046
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1047
+ const markerData: any = markerSetting.dataSource[dataIndex];
1048
+ let factor: number; let location: Point;
1049
+ const longitude: number = (!isNullOrUndefined(markerSetting.longitudeValuePath)) ?
1050
+ Number(getValueFromObject(markerData, markerSetting.longitudeValuePath)) :
1051
+ !isNullOrUndefined(markerData['longitude']) ? parseFloat(markerData['longitude']) :
1052
+ !isNullOrUndefined(markerData['Latitude']) ? parseFloat(markerData['Latitude']) : 0;
1053
+ const latitude: number = (!isNullOrUndefined(markerSetting.latitudeValuePath)) ?
1054
+ Number(getValueFromObject(markerData, markerSetting.latitudeValuePath)) :
1055
+ !isNullOrUndefined(markerData['latitude']) ? parseFloat(markerData['latitude']) :
1056
+ !isNullOrUndefined(markerData['Latitude']) ? parseFloat(markerData['Latitude']) : 0;
1057
+ if (!maps.isTileMap) {
1058
+ factor = maps.mapLayerPanel.calculateFactor(currentLayer);
1059
+ location = convertGeoToPoint(latitude, longitude, factor, currentLayer, maps);
1060
+ } else if (maps.isTileMap && !maps.zoomSettings.enable) {
1061
+ location = convertTileLatLongToPoint(new Point(longitude, latitude), maps.tileZoomLevel, maps.tileTranslatePoint, true);
1062
+ }
1063
+ markerTemplate.childNodes[o]['style']['visibility'] = 'hidden';
1064
+ const clusters: MarkerClusterSettingsModel = currentLayer.markerClusterSettings;
1065
+ if (eventArg.cancel) {
1066
+ shapeCustom = {
1067
+ size: new Size(clusters.width, clusters.height),
1068
+ fill: clusters.fill, borderColor: clusters.border.color,
1069
+ borderWidth: clusters.border.width, opacity: clusters.opacity,
1070
+ dashArray: clusters.dashArray
1071
+ };
1072
+ shapeCustom['fill'] = clusters.fill;
1073
+ shapeCustom['size']['width'] = clusters.width;
1074
+ shapeCustom['size']['height'] = clusters.height;
1075
+ shapeCustom['imageUrl'] = clusters.imageUrl;
1076
+ shapeCustom['shape'] = clusters.shape;
1077
+ shapeCustom['borderColor'] = clusters.border.color;
1078
+ shapeCustom['borderWidth'] = clusters.border.width;
1079
+ shapeCustom['borderOpacity'] = isNullOrUndefined(clusters.border.opacity) ? clusters.opacity : clusters.border.opacity;
1080
+ } else {
1081
+ shapeCustom = {
1082
+ size: new Size(clusters.width, clusters.height),
1083
+ fill: clusters.fill, borderColor: clusters.border.color,
1084
+ borderWidth: clusters.border.width, opacity: clusters.opacity,
1085
+ dashArray: clusters.dashArray
1086
+ };
1087
+ shapeCustom['fill'] = eventArg.fill;
1088
+ shapeCustom['size']['width'] = eventArg.width;
1089
+ shapeCustom['size']['height'] = eventArg.height;
1090
+ shapeCustom['imageUrl'] = eventArg.imageUrl;
1091
+ shapeCustom['shape'] = eventArg.shape;
1092
+ shapeCustom['borderColor'] = eventArg.border.color;
1093
+ shapeCustom['borderWidth'] = eventArg.border.width;
1094
+ shapeCustom['borderOpacity'] = isNullOrUndefined(eventArg.border.opacity) ? clusters.opacity : eventArg.border.opacity;
1095
+ }
1096
+ tempX = (maps.isTileMap) ? tempX : (markerTemplate.id.indexOf('_Markers_Group') > -1) ? tempX : tempX + postionY - (eventArg.width / 2);
1097
+ tempY = (maps.isTileMap) ? tempY : (markerTemplate.id.indexOf('_Markers_Group') > -1) ? tempY : tempY - (eventArg.height / 2);
1098
+ if (maps.isTileMap && !maps.zoomSettings.enable) {
1099
+ tempX = location.x;
1100
+ tempY = location.y;
1101
+ }
1102
+ const clusterID: string = maps.element.id + '_LayerIndex_' + layerIndex + '_MarkerIndex_' + markerIndex + '_dataIndex_' + dataIndex + '_cluster_' + (m);
1103
+ const labelID: string = maps.element.id + '_LayerIndex_' + layerIndex + '_MarkerIndex_' + markerIndex + '_dataIndex_' + dataIndex + '_cluster_' + (m) + '_datalabel_' + m;
1104
+ m++;
1105
+ const imageShapeY: number = shapeCustom['shape'] === 'Image' ? shapeCustom['size']['height'] / 2 : 0;
1106
+ const ele: Element = drawSymbols(
1107
+ shapeCustom['shape'], shapeCustom['imageUrl'], { x: 0, y: imageShapeY },
1108
+ clusterID, shapeCustom, markerCollection, maps
1109
+ );
1110
+ ele.setAttribute('transform', 'translate( ' + tempX + ' ' + tempY + ' )');
1111
+ if (eventArg.shape === 'Balloon') {
1112
+ ele.children[0].innerHTML = indexCollection.toString();
1113
+ } else {
1114
+ ele.innerHTML = indexCollection.toString();
1115
+ }
1116
+ options = new TextOption(labelID, (0), postionY, 'middle', (colloideBounds.length + 1).toString(), '', '');
1117
+ textElement = renderTextElement(options, style, style.color, markerCollection);
1118
+ textElement.setAttribute('transform', 'translate( ' + tempX + ' ' + tempY + ' )');
1119
+ clusterGroup.appendChild(textElement);
1120
+ clusterGroup.appendChild(ele);
1121
+ }
1122
+ }
1123
+ colloideBounds = [];
1124
+ }
1125
+ }
1126
+ layerElement.appendChild(clusterGroup);
1127
+ maps.svgObject.appendChild(layerElement) as Element;
1128
+ maps.element.appendChild(maps.svgObject) as Element;
1129
+ for (let o: number = 0; o < clusterGroup.childElementCount; o++) {
1130
+ if (clusterGroup.childNodes[o]['style']['visibility'] !== 'hidden') {
1131
+ tempElement = clusterGroup.childNodes[o] as Element;
1132
+ bounds1 = tempElement.getBoundingClientRect() as DOMRect;
1133
+ if (!isNullOrUndefined(bounds1) && !(tempElement.id.indexOf('_datalabel_') > -1)) {
1134
+ for (let p: number = o + 1; p < clusterGroup.childElementCount; p++) {
1135
+ if (clusterGroup.childNodes[p]['style']['visibility'] !== 'hidden') {
1136
+ tempElement1 = clusterGroup.childNodes[p] as Element;
1137
+ bounds2 = tempElement1.getBoundingClientRect() as DOMRect;
1138
+ if (!isNullOrUndefined(bounds2) && !(tempElement1.id.indexOf('_datalabel_') > -1)) {
1139
+ if (!(bounds1.left > bounds2.right || bounds1.right < bounds2.left
1140
+ || bounds1.top > bounds2.bottom || bounds1.bottom < bounds2.top)) {
1141
+ clusterColloideBounds.push(tempElement1);
1142
+ clusterColloideBounds.push(clusterGroup.childNodes[p - 1] as Element);
1143
+ clusterGroup.childNodes[p]['style']['visibility'] = 'hidden';
1144
+ clusterGroup.childNodes[p - 1]['style']['visibility'] = 'hidden';
1145
+ indexCollection.push(p as number);
1146
+ }
1147
+ }
1148
+ }
1149
+ }
1150
+ if (clusterColloideBounds.length > 0) {
1151
+ tempElement = clusterGroup.childNodes[o] as Element;
1152
+ for (let i: number = 0; i < clusterColloideBounds.length; i++) {
1153
+ if (tempElement.tagName === 'g') {
1154
+ tempElement.childNodes[0].textContent = tempElement.childNodes[0].textContent + ',' +
1155
+ clusterColloideBounds[i].textContent;
1156
+ } else {
1157
+ tempElement.textContent = tempElement.textContent + ',' + clusterColloideBounds[i].textContent;
1158
+ }
1159
+ clusterGroup.childNodes[o - 1].textContent = ((+(clusterGroup.childNodes[o - 1].textContent)) + (+(clusterColloideBounds[i + 1].textContent))).toString();
1160
+ i++;
1161
+ }
1162
+ }
1163
+ clusterColloideBounds = [];
1164
+ }
1165
+ }
1166
+ }
1167
+ while (0 < clusterGroup.childNodes.length) {
1168
+ markerCollection.insertBefore(clusterGroup.childNodes[0], markerCollection.firstChild);
1169
+ }
1170
+ if (check) {
1171
+ layerElement.appendChild(markerCollection);
1172
+ } else {
1173
+ getElementByID(maps.element.id + '_Secondary_Element').appendChild(markerCollection);
1174
+ layerElement.appendChild(markerCollection);
1175
+ }
1176
+ const markerCluster: HTMLElement = document.getElementById(maps.element.id + '_LayerIndex_' + layerIndex +'_markerCluster');
1177
+ if (!isNullOrUndefined(markerCluster)) {
1178
+ markerCluster.remove();
1179
+ }
1180
+ if (zoomCheck) {
1181
+ let layerGroupElement: HTMLElement = document.getElementById(maps.element.id + '_Layer_Collections');
1182
+ if (!isNullOrUndefined(layerGroupElement)) {
1183
+ layerGroupElement.appendChild(layerElement);
1184
+ }
1185
+ }
1186
+ });
1187
+ }
1188
+
1189
+ /**
1190
+ *
1191
+ * @param {MarkerClusterData[]} sameMarkerData - Specifies the marker data
1192
+ * @param {Maps} maps - Specifies the instance of the maps
1193
+ * @param {Element | HTMLElement} markerElement - Specifies the marker element
1194
+ * @returns {void}
1195
+ */
1196
+ export function mergeSeparateCluster(sameMarkerData: MarkerClusterData[], maps: Maps, markerElement: Element | HTMLElement): void {
1197
+ const layerIndex: number = sameMarkerData[0].layerIndex;
1198
+ const clusterIndex: number = sameMarkerData[0].targetClusterIndex;
1199
+ const markerIndex: number = sameMarkerData[0].markerIndex;
1200
+ const dataIndex: number = sameMarkerData[0].dataIndex;
1201
+ const markerId: string = maps.element.id + '_LayerIndex_' + layerIndex + '_MarkerIndex_' + markerIndex;
1202
+ const marker: MarkerSettingsModel = maps.layers[layerIndex].markerSettings[markerIndex];
1203
+ const clusterId: string = markerId + '_dataIndex_' + dataIndex + '_cluster_' + clusterIndex;
1204
+ const clusterEle: Element = maps.layers[layerIndex].markerClusterSettings.shape === 'Balloon' ? getElement(clusterId + '_Group') : getElement(clusterId);
1205
+ const clusterEleLabel: Element = getElement(clusterId + '_datalabel_' + clusterIndex);
1206
+ clusterEle.setAttribute('visibility', 'visible');
1207
+ clusterEleLabel.setAttribute('visibility', 'visible');
1208
+ let markerEle: Element;
1209
+ const markerDataLength: number = sameMarkerData[0].data.length;
1210
+ for (let i: number = 0; i < markerDataLength; i++) {
1211
+ markerEle = marker.shape === 'Balloon' ? getElement(markerId + '_dataIndex_' + sameMarkerData[0].data[i]['index'] + '_Group') : getElement(markerId + '_dataIndex_' + sameMarkerData[0].data[i]['index']);
1212
+ markerEle['style']['visibility'] = 'hidden';
1213
+ }
1214
+ removeElement(maps.element.id + '_LayerIndex_' + layerIndex + '_MarkerIndex_' + markerIndex + '_markerClusterConnectorLine');
1215
+ }
1216
+
1217
+ /**
1218
+ *
1219
+ * @param {MarkerClusterData[]} sameMarkerData - Specifies the marker data
1220
+ * @param {Maps} maps - Specifies the instance of the maps
1221
+ * @param {Element | HTMLElement} markerElement - Specifies the marker element
1222
+ * @param {boolean} isDom - Specifies the boolean value
1223
+ * @returns {void}
1224
+ */
1225
+ export function clusterSeparate(sameMarkerData: MarkerClusterData[], maps: Maps, markerElement: Element | HTMLElement, isDom?: boolean): void {
1226
+ const layerIndex: number = sameMarkerData[0].layerIndex;
1227
+ const markerIndex: number = sameMarkerData[0].markerIndex;
1228
+ const clusterIndex: number = sameMarkerData[0].targetClusterIndex;
1229
+ const dataIndex: number = sameMarkerData[0].dataIndex;
1230
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1231
+ const getElementFunction: any = isDom ? getElement : markerElement.querySelector.bind(markerElement);
1232
+ const getQueryConnect: string = isDom ? '' : '#';
1233
+ const markerId: string = maps.element.id + '_LayerIndex_' + layerIndex + '_MarkerIndex_' + markerIndex;
1234
+ const marker: MarkerSettingsModel = maps.layers[layerIndex].markerSettings[markerIndex];
1235
+ const clusterId: string = markerId + '_dataIndex_' + dataIndex + '_cluster_' + clusterIndex;
1236
+ const clusterEle: Element = maps.layers[layerIndex].markerClusterSettings.shape === 'Balloon' ? getElementFunction(getQueryConnect + '' + clusterId + '_Group') : getElementFunction(getQueryConnect + '' + clusterId);
1237
+ const clusterEleLabel: Element = getElementFunction(getQueryConnect + '' + clusterId + '_datalabel_' + clusterIndex);
1238
+ clusterEle.setAttribute('visibility', 'hidden');
1239
+ clusterEleLabel.setAttribute('visibility', 'hidden');
1240
+ let markerEle: Element = marker.shape === 'Balloon' ? getElementFunction(getQueryConnect + '' + markerId + '_dataIndex_' + dataIndex + '_Group') : getElementFunction(getQueryConnect + '' + markerId + '_dataIndex_' + dataIndex);
1241
+ const height: number = markerEle.parentElement.id.indexOf('Template_Group') > -1 ? markerEle.getBoundingClientRect().height : marker.height;
1242
+ const width: number = markerEle.parentElement.id.indexOf('Template_Group') > -1 ? markerEle.getBoundingClientRect().width : marker.width;
1243
+ const centerX: number = +clusterEle.getAttribute('transform').split('translate(')[1].trim().split(' ')[0];
1244
+ const centerY: number = +clusterEle.getAttribute('transform').split('translate(')[1].trim().split(' ')[1].split(')')[0].trim();
1245
+
1246
+ let radius: number = width + 5;
1247
+ let area: number = 2 * 3.14 * radius;
1248
+ let totalMarker: number = 0;
1249
+ let numberOfMarker: number = Math.round(area / width);
1250
+ totalMarker += numberOfMarker;
1251
+ const markerDataLength: number = sameMarkerData[0].data.length;
1252
+ let percent: number = Math.round((height / area) * 100);
1253
+ percent = markerDataLength < numberOfMarker ? 100 / markerDataLength : percent;
1254
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1255
+ let angle: any = (percent / 100) * 360;
1256
+ let newAngle: number = markerDataLength < numberOfMarker ? 45 : 0;
1257
+ let count: number = 1;
1258
+ const start: string = 'M ' + centerX + ' ' + centerY + ' ';
1259
+ let path: string = '';
1260
+ for (let i: number = 0; i < markerDataLength; i++) {
1261
+ if (totalMarker === i || Math.round(newAngle) >= 360) {
1262
+ count++;
1263
+ radius = (width + 5) * count;
1264
+ newAngle = 0;
1265
+ area = 2 * 3.14 * radius;
1266
+ numberOfMarker = Math.round(area / height);
1267
+ percent = Math.round((height / area) * 100);
1268
+ while (percent * numberOfMarker < 100) {
1269
+ numberOfMarker++;
1270
+ }
1271
+ angle = ((percent / 100) * 360);
1272
+ totalMarker += numberOfMarker;
1273
+ }
1274
+ const x1: number = centerX + radius * Math.sin((Math.PI * 2 * newAngle) / 360);
1275
+ const y1: number = centerY + radius * Math.cos((Math.PI * 2 * newAngle) / 360);
1276
+ path += start + 'L ' + (x1) + ' ' + y1 + ' ';
1277
+ markerEle = marker.shape === 'Balloon' ? getElementFunction(getQueryConnect + '' + markerId + '_dataIndex_' + sameMarkerData[0].data[i]['index'] + '_Group') : getElementFunction(getQueryConnect + '' + markerId + '_dataIndex_' + sameMarkerData[0].data[i]['index']);
1278
+ if (markerEle.parentElement.id.indexOf('Template_Group') > -1) {
1279
+ markerEle['style']['transform'] = '';
1280
+ markerEle['style']['left'] = maps.isTileMap ? x1 - (width / 2) + 'px' : (x1 - (width / 2) - 10) + 'px';
1281
+ markerEle['style']['top'] = maps.isTileMap ? y1 - (height / 2) + 'px' : (y1 - (height / 2) - 10) + 'px';
1282
+ markerEle.setAttribute('transform', 'translate( ' + x1 + ' ' + y1 + ')');
1283
+ } else {
1284
+ markerEle.setAttribute('transform', 'translate( ' + x1 + ' ' + y1 + ')');
1285
+ }
1286
+ markerEle['style']['visibility'] = 'visible';
1287
+ newAngle += angle;
1288
+ }
1289
+ const connectorLine: ConnectorLineSettingsModel = maps.layers[layerIndex].markerClusterSettings.connectorLineSettings;
1290
+ const options: PathOption = {
1291
+ d: path, id: maps.element.id + '_LayerIndex_' + layerIndex + '_MarkerIndex_' + markerIndex + '_dataIndex_' + dataIndex + '_markerClusterConnectorLine', stroke: connectorLine.color,
1292
+ 'fill-opacity': connectorLine.opacity, 'stroke-opacity': connectorLine.opacity, 'stroke-width': connectorLine.width
1293
+ } as PathOption;
1294
+ markerElement = isDom ? getElementFunction(maps.element.id + '_Markers_Group') : markerElement;
1295
+ const groupEle: Element = maps.renderer.createGroup({ id: maps.element.id + '_LayerIndex_' + layerIndex + '_MarkerIndex_' + markerIndex + '_markerClusterConnectorLine' });
1296
+ groupEle.appendChild(maps.renderer.drawPath(options));
1297
+ if (marker.shape === 'Balloon') {
1298
+ markerElement.insertBefore(groupEle, markerElement.querySelector('#' + markerId + '_dataIndex_0_Group'));
1299
+ } else {
1300
+ markerElement.insertBefore(groupEle, markerElement.querySelector('#' + markerId + '_dataIndex_0'));
1301
+ }
1302
+ }
1303
+
1304
+ /**
1305
+ *
1306
+ * @param {IMarkerRenderingEventArgs} eventArgs - Specifies the arguments
1307
+ * @param {MarkerSettings} markerSettings - Specifies the marker settings
1308
+ * @param {any[]} markerData - Specifies the marker data
1309
+ * @param {number} dataIndex - Specifies the data index
1310
+ * @param {Point} location - Specifies the location
1311
+ * @param {Point} transPoint - Specifies the translate point
1312
+ * @param {string} markerID - Specifies the marker id
1313
+ * @param {Point} offset - Specifies the offset value
1314
+ * @param {number} scale - Specifies the scale value
1315
+ * @param {Maps} maps - Specifies the instance of the maps
1316
+ * @param {Element} markerCollection - Specifies the marker collection
1317
+ * @returns {Element} - Returns the element
1318
+ */
1319
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1320
+ export function marker(eventArgs: IMarkerRenderingEventArgs, markerSettings: MarkerSettings, markerData: any[], dataIndex: number,
1321
+ location: Point, transPoint: Point, markerID: string, offset: Point, scale: number, maps: Maps,
1322
+ markerCollection: Element): Element {
1323
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1324
+ const shapeCustom: any = {
1325
+ size: new Size(eventArgs.width, eventArgs.height),
1326
+ fill: eventArgs.fill, borderColor: eventArgs.border.color,
1327
+ borderWidth: eventArgs.border.width, opacity: markerSettings.opacity,
1328
+ dashArray: markerSettings.dashArray, borderOpacity: isNullOrUndefined(eventArgs.border.opacity) ? markerSettings.opacity :
1329
+ eventArgs.border.opacity
1330
+ };
1331
+ removeElement(markerID);
1332
+ const ele: Element = drawSymbols(eventArgs.shape, eventArgs.imageUrl, { x: 0, y: 0 }, markerID, shapeCustom, markerCollection, maps);
1333
+ const x: number = (maps.isTileMap ? location.x : (location.x + transPoint.x) * scale) + offset.x;
1334
+ const y: number = (maps.isTileMap ? location.y : (location.y + transPoint.y) * scale) + offset.y;
1335
+ ele.setAttribute('transform', 'translate( ' + x + ' ' + y + ' )');
1336
+ maintainSelection(maps.selectedMarkerElementId, maps.markerSelectionClass, ele, 'MarkerselectionMapStyle');
1337
+ markerCollection.appendChild(ele);
1338
+ const element: string = (markerData.length - 1) === dataIndex ? 'marker' : null;
1339
+ const markerPoint: Point = new Point(x, y);
1340
+ if (markerSettings.animationDuration > 0) {
1341
+ elementAnimate(
1342
+ ele, markerSettings.animationDelay, markerSettings.animationDuration, markerPoint, maps, element
1343
+ );
1344
+ }
1345
+ return markerCollection;
1346
+ }
1347
+
1348
+ /**
1349
+ *
1350
+ * @param {IMarkerRenderingEventArgs} eventArgs - Specifies the arguments
1351
+ * @param {any} templateFn - Specifies the template function
1352
+ * @param {string} markerID - Specifies the marker id
1353
+ * @param {any} data - Specifies the data
1354
+ * @param {number} markerIndex - Specifies the marker index
1355
+ * @param {HTMLElement} markerTemplate - Specifies the marker template element
1356
+ * @param {Point} location - Specifies the location
1357
+ * @param {Point} transPoint - Specifies the translate point.
1358
+ * @param {number} scale - Specifies the scale value
1359
+ * @param {Point} offset - Specifies the offset value
1360
+ * @param {Maps} maps - Specifies the instance of the maps
1361
+ * @returns {HTMLElement} - Returns the html element
1362
+ */
1363
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1364
+ export function markerTemplate(eventArgs: IMarkerRenderingEventArgs, templateFn: any, markerID: string, data: any,
1365
+ markerIndex: number, markerTemplate: HTMLElement, location: Point, transPoint: Point, scale: number, offset: Point, maps: Maps): HTMLElement {
1366
+ templateFn = getTemplateFunction(eventArgs.template, maps);
1367
+ if (templateFn && (templateFn(data, maps, eventArgs.template, maps.element.id + '_MarkerTemplate' + markerIndex, false).length)) {
1368
+ const templateElement: HTMLCollection = templateFn(data, maps, eventArgs.template, maps.element.id + '_MarkerTemplate' + markerIndex, false);
1369
+ const markerElement: HTMLElement = <HTMLElement>convertElement(
1370
+ templateElement, markerID, data, markerIndex, maps
1371
+ );
1372
+ for (let i: number = 0; i < markerElement.children.length; i++) {
1373
+ (<HTMLElement>markerElement.children[i]).style.pointerEvents = 'none';
1374
+ }
1375
+ markerElement.style.left = (maps.isTileMap ? location.x : (location.x + transPoint.x) * scale) + offset.x - maps.mapAreaRect.x + 'px';
1376
+ markerElement.style.top = (maps.isTileMap ? location.y : (location.y + transPoint.y) * scale) + offset.y - maps.mapAreaRect.y + 'px';
1377
+ markerTemplate.appendChild(markerElement);
1378
+ if (maps.layers[maps.baseLayerIndex].layerType === 'GoogleStaticMap') {
1379
+ const staticMapOffset: ClientRect = getElementByID(maps.element.id + '_StaticGoogleMap').getBoundingClientRect();
1380
+ const markerElementOffset: ClientRect = markerElement.getBoundingClientRect();
1381
+ const staticMapOffsetWidth: number = 640;
1382
+ if ((staticMapOffset['x'] > markerElementOffset['x'] || staticMapOffset['x'] + staticMapOffsetWidth < markerElementOffset['x'] + markerElementOffset['width'])
1383
+ && (staticMapOffset['y'] > markerElementOffset['y'] || staticMapOffset['y'] + staticMapOffset['height'] < markerElementOffset['y'] + markerElementOffset['height'])
1384
+ ) {
1385
+ markerElement.style.display = 'none';
1386
+ }
1387
+ }
1388
+
1389
+ }
1390
+ return markerTemplate;
1391
+ }
1392
+
1393
+ /**
1394
+ * To maintain selection during page resize
1395
+ *
1396
+ * @param {string[]} elementId - Specifies the element id
1397
+ * @param {Element} elementClass - Specifies the element class
1398
+ * @param {Element} element - Specifies the element
1399
+ * @param {string} className - Specifies the class name
1400
+ * @returns {void}
1401
+ * @private
1402
+ */
1403
+ export function maintainSelection(elementId: string[], elementClass: Element, element: Element, className: string): void {
1404
+ if (elementId) {
1405
+ for (let index: number = 0; index < elementId.length; index++) {
1406
+ if (element.getAttribute('id') === elementId[index]) {
1407
+ if (index === 0 || element.tagName === 'g') {
1408
+ if (!isNullOrUndefined(elementClass) && !isNullOrUndefined(elementClass.id)) {
1409
+ document.body.appendChild(elementClass);
1410
+ }
1411
+ if (element.id.indexOf('_MarkerIndex_') > -1 && element.childElementCount > 0) {
1412
+ element.children[0].setAttribute('class', className);
1413
+ }
1414
+ }
1415
+ element.setAttribute('class', className);
1416
+ }
1417
+ }
1418
+ }
1419
+ }
1420
+
1421
+ /**
1422
+ * To maintain selection style class
1423
+ *
1424
+ * @param {string} id - Specifies the id
1425
+ * @param {string} idClass - Specifies the class id
1426
+ * @param {string} fill - Specifies the fill
1427
+ * @param {string} opacity - Specifies the opactiy
1428
+ * @param {string} borderColor - Specifies the border color
1429
+ * @param {string} borderWidth - Specifies the border width
1430
+ * @param {Maps} maps - Specifies the maps
1431
+ * @returns {void}
1432
+ * @private
1433
+ */
1434
+ export function maintainStyleClass(id: string, idClass: string, fill: string, opacity: string, borderColor: string,
1435
+ borderWidth: string, maps: Maps): void {
1436
+ if (!getElement(id)) {
1437
+ const styleClass: Element = createElement('style', {
1438
+ id: id, innerHTML: '.' + idClass + '{fill:'
1439
+ + fill + ';' + 'opacity:' + opacity + ';' +
1440
+ 'stroke-width:' + borderWidth + ';' +
1441
+ 'stroke:' + borderColor + ';' + '}'
1442
+ });
1443
+ maps.shapeSelectionClass = styleClass;
1444
+ document.body.appendChild(styleClass);
1445
+ }
1446
+ }
1447
+
1448
+ /**
1449
+ * Internal use of append shape element
1450
+ *
1451
+ * @param {Element} shape - Specifies the shape
1452
+ * @param {Element} element - Specifies the element
1453
+ * @returns {Element} - Returns the element
1454
+ * @private
1455
+ */
1456
+ export function appendShape(shape: Element, element: Element): Element {
1457
+ if (element) { element.appendChild(shape); }
1458
+ return shape;
1459
+ }
1460
+ /**
1461
+ * Internal rendering of Circle
1462
+ *
1463
+ * @param {Maps} maps - Specifies the instance of the maps
1464
+ * @param {CircleOption} options - Specifies the circle options
1465
+ * @param {Element} element - Specifies the element
1466
+ * @returns {Element} - Returns the element
1467
+ * @private
1468
+ */
1469
+ export function drawCircle(maps: Maps, options: CircleOption, element?: Element): Element {
1470
+ return appendShape(maps.renderer.drawCircle(options), element);
1471
+ }
1472
+ /**
1473
+ * Internal rendering of Rectangle
1474
+ *
1475
+ * @param {Maps} maps - Specifies the instance of the maps
1476
+ * @param {RectOption} options - Specifies the rect options
1477
+ * @param {Element} element - Specifies the element
1478
+ * @returns {Element} - Returns the element
1479
+ * @private
1480
+ */
1481
+ export function drawRectangle(maps: Maps, options: RectOption, element?: Element): Element {
1482
+ return appendShape(maps.renderer.drawRectangle(options), element);
1483
+ }
1484
+ /**
1485
+ * Internal rendering of Path
1486
+ *
1487
+ * @param {Maps} maps - Specifies the instance of the maps
1488
+ * @param {PathOption} options - Specifies the polygon options
1489
+ * @param {Element} element - Specifies the element
1490
+ * @returns {Element} - Returns the element
1491
+ * @private
1492
+ */
1493
+ export function drawPath(maps: Maps, options: PathOption, element?: Element): Element {
1494
+ return appendShape(maps.renderer.drawPath(options), element);
1495
+ }
1496
+ /**
1497
+ * Internal rendering of Polygon
1498
+ *
1499
+ * @param {Maps} maps - Specifies the instance of the maps
1500
+ * @param {PolygonOption} options - Specifies the polygon options
1501
+ * @param {Element} element - Specifies the element
1502
+ * @returns {Element} - Returns the element
1503
+ * @private
1504
+ */
1505
+ export function drawPolygon(maps: Maps, options: PolygonOption, element?: Element): Element {
1506
+ return appendShape(maps.renderer.drawPolygon(options), element);
1507
+ }
1508
+ /**
1509
+ * Internal rendering of Polyline
1510
+ *
1511
+ * @param {Maps} maps - Specifies the instance of the maps
1512
+ * @param {PolylineOption} options - Specifies the poly line options
1513
+ * @param {Element} element - Specifies the element
1514
+ * @returns {Element} - Returns the element
1515
+ * @private
1516
+ */
1517
+ export function drawPolyline(maps: Maps, options: PolylineOption, element?: Element): Element {
1518
+ return appendShape(maps.renderer.drawPolyline(options), element);
1519
+ }
1520
+ /**
1521
+ * Internal rendering of Line
1522
+ *
1523
+ * @param {Maps} maps - Specifies the instance of the maps
1524
+ * @param {LineOption} options - Specifies the line options
1525
+ * @param {Element} element - Specifies the element
1526
+ * @returns {Element} - Returns the element
1527
+ * @private
1528
+ */
1529
+ export function drawLine(maps: Maps, options: LineOption, element?: Element): Element {
1530
+ return appendShape(maps.renderer.drawLine(options), element);
1531
+ }
1532
+
1533
+ /**
1534
+ * Calculate marker shapes
1535
+ *
1536
+ * @param {Maps} maps - Specifies the instance of the maps
1537
+ * @param {MarkerType} shape - Specifies the marker type
1538
+ * @param {PathOption} options - Specifies the path options
1539
+ * @param {Size} size - Specifies the size
1540
+ * @param {MapLocation} location - Specifies the map location
1541
+ * @param {Element} markerEle - Specifies the element
1542
+ * @returns {Element} - Returns the element
1543
+ * @private
1544
+ */
1545
+ export function calculateShapes(
1546
+ maps: Maps, shape: MarkerType, options: PathOption, size: Size, location: MapLocation, markerEle: Element
1547
+ ): Element {
1548
+ let tempGroup: Element;
1549
+ switch (shape) {
1550
+ case 'Balloon':
1551
+ tempGroup = drawBalloon(maps, options, size, location, 'Marker', markerEle);
1552
+ break;
1553
+ case 'Cross':
1554
+ options.d = 'M ' + location.x + ' ' + (location.y - size.height / 2) + ' L ' + location.x + ' ' + (location.y + size.height
1555
+ / 2) + ' M ' + (location.x - size.width / 2) + ' ' + location.y + ' L ' + (location.x + size.width / 2) + ' ' + location.y;
1556
+ break;
1557
+ case 'Diamond':
1558
+ options.d = 'M ' + location.x + ' ' + (location.y - size.height / 2) + ' L ' + (location.x + size.width / 2) + ' '
1559
+ + location.y + ' L ' + location.x + ' ' + (location.y + size.height / 2) + ' L ' + (location.x - size.width / 2)
1560
+ + ' ' + location.y + ' Z';
1561
+ break;
1562
+ case 'Star':
1563
+ options.d = 'M ' + (location.x + size.width / 3) + ' ' + (location.y - size.height / 2) + ' L ' + (location.x - size.width / 2)
1564
+ + ' ' + (location.y + size.height / 6) + ' L ' + (location.x + size.width / 2) + ' ' + (location.y + size.height / 6)
1565
+ + ' L ' + (location.x - size.width / 3) + ' ' + (location.y - size.height / 2) + ' L ' + location.x + ' ' +
1566
+ (location.y + size.height / 2) + ' L ' + (location.x + size.width / 3) + ' ' + (location.y - size.height / 2) + ' Z';
1567
+ break;
1568
+ case 'Triangle':
1569
+ options.d = 'M ' + location.x + ' ' + (location.y - size.height / 2) + ' L ' + (location.x + size.width / 2) + ' ' +
1570
+ (location.y + size.height / 2) + ' L ' + (location.x - size.width / 2) + ' ' + (location.y + size.height / 2) + ' Z';
1571
+ break;
1572
+ case 'HorizontalLine':
1573
+ options.d = ' M ' + (location.x - size.width / 2) + ' ' + location.y + ' L ' + (location.x + size.width / 2) + ' '
1574
+ + location.y;
1575
+ break;
1576
+ case 'VerticalLine':
1577
+ options.d = 'M ' + location.x + ' ' + (location.y - size.height / 2) + ' L ' + location.x + ' ' +
1578
+ (location.y + size.height / 2);
1579
+ break;
1580
+ case 'InvertedTriangle':
1581
+ options.d = 'M ' + (location.x - size.width / 2) + ' ' + (location.y - size.height / 2) + ' L ' + (location.x + size.width / 2) + ' ' +
1582
+ (location.y - size.height / 2) + ' L ' + (location.x) + ' ' + (location.y + size.height / 2) + ' Z';
1583
+ break;
1584
+ case 'Pentagon':
1585
+ // eslint-disable-next-line no-case-declarations
1586
+ const eq: number = 72; let xValue: number; let yValue: number;
1587
+ for (let i: number = 0; i < 5; i++) {
1588
+ xValue = (size.width / 2) * Math.cos((Math.PI / 180) * (i * eq));
1589
+ yValue = (size.height / 2) * Math.sin((Math.PI / 180) * (i * eq));
1590
+ options.d += (i === 0 ? 'M ' : 'L ') + (location.x + xValue) + ' ' + (location.y + yValue);
1591
+ }
1592
+ options.d += ' Z';
1593
+ break;
1594
+ }
1595
+ if (shape === 'Cross' || shape === 'HorizontalLine' || shape === 'VerticalLine') {
1596
+ options['stroke'] = (options['stroke'] === 'transparent') ? options['fill'] : options['stroke'];
1597
+ }
1598
+ return shape === 'Balloon' ? tempGroup : maps.renderer.drawPath(options);
1599
+ }
1600
+
1601
+
1602
+ /**
1603
+ * Internal rendering of Diamond
1604
+ *
1605
+ * @param {Maps} maps - Specifies the instance of the maps
1606
+ * @param {PathOption} options - Specifies the path options
1607
+ * @param {Size} size - Specifies the size
1608
+ * @param {MapLocation} location - Specifies the map location
1609
+ * @param {Element} element - Specifies the element
1610
+ * @returns {Element} - Returns the element
1611
+ * @private
1612
+ */
1613
+ export function drawDiamond(maps: Maps, options: PathOption, size: Size, location: MapLocation, element?: Element): Element {
1614
+ options.d = 'M ' + location.x + ' ' + (location.y - size.height / 2) + ' L ' + (location.x + size.width / 2) + ' ' + location.y +
1615
+ ' L ' + location.x + ' ' + (location.y + size.height / 2) + ' L ' + (location.x - size.width / 2) + ' ' + location.y + ' Z';
1616
+ return appendShape(maps.renderer.drawPath(options), element);
1617
+ }
1618
+ /**
1619
+ * Internal rendering of Triangle
1620
+ *
1621
+ * @param {Maps} maps - Specifies the instance of the maps
1622
+ * @param {PathOption} options - Specifies the path options
1623
+ * @param {Size} size - Specifies the size
1624
+ * @param {MapLocation} location - Specifies the map location
1625
+ * @param {Element} element - Specifies the element
1626
+ * @returns {Element} - Returns the element
1627
+ * @private
1628
+ */
1629
+ export function drawTriangle(maps: Maps, options: PathOption, size: Size, location: MapLocation, element?: Element): Element {
1630
+ options.d = 'M ' + location.x + ' ' + (location.y - size.height / 2) + ' L ' + (location.x + size.width / 2) + ' ' +
1631
+ (location.y + size.height / 2) + ' L ' + (location.x - size.width / 2) + ' ' + (location.y + size.height / 2) + ' Z';
1632
+ return appendShape(maps.renderer.drawPath(options), element);
1633
+ }
1634
+ /**
1635
+ * Internal rendering of Cross
1636
+ *
1637
+ * @param {Maps} maps - Specifies the instance of the maps
1638
+ * @param {PathOption} options - Specifies the path options
1639
+ * @param {Size} size - Specifies the size
1640
+ * @param {MapLocation} location - Specifies the map location
1641
+ * @param {Element} element - Specifies the element
1642
+ * @returns {Element} - Returns the element
1643
+ * @private
1644
+ */
1645
+ export function drawCross(maps: Maps, options: PathOption, size: Size, location: MapLocation, element?: Element): Element {
1646
+ options.d = 'M ' + location.x + ' ' + (location.y - size.height / 2) + ' L ' + location.x + ' ' + (location.y + size.height / 2) +
1647
+ ' M ' + (location.x - size.width / 2) + ' ' + location.y + ' L ' + (location.x + size.width / 2) + ' ' + location.y;
1648
+ return appendShape(maps.renderer.drawPath(options), element);
1649
+ }
1650
+ /**
1651
+ * Internal rendering of HorizontalLine
1652
+ *
1653
+ * @param {Maps} maps - Specifies the instance of the maps
1654
+ * @param {PathOption} options - Specifies the path options
1655
+ * @param {Size} size - Specifies the size
1656
+ * @param {MapLocation} location - Specifies the map location
1657
+ * @param {Element} element - Specifies the element
1658
+ * @returns {Element} - Returns the element
1659
+ * @private
1660
+ */
1661
+ export function drawHorizontalLine(maps: Maps, options: PathOption, size: Size, location: MapLocation, element?: Element): Element {
1662
+ options.d = ' M ' + (location.x - size.width / 2) + ' ' + location.y + ' L ' + (location.x + size.width / 2) + ' ' + location.y;
1663
+ return appendShape(maps.renderer.drawPath(options), element);
1664
+ }
1665
+ /**
1666
+ * Internal rendering of VerticalLine
1667
+ *
1668
+ * @param {Maps} maps - Specifies the instance of the maps
1669
+ * @param {PathOption} options - Specifies the path options
1670
+ * @param {Size} size - Specifies the size
1671
+ * @param {MapLocation} location - Specifies the map location
1672
+ * @param {Element} element - Specifies the element
1673
+ * @returns {Element} - Returns the element
1674
+ * @private
1675
+ */
1676
+ export function drawVerticalLine(maps: Maps, options: PathOption, size: Size, location: MapLocation, element?: Element): Element {
1677
+ options.d = 'M ' + location.x + ' ' + (location.y - size.height / 2) + ' L ' + location.x + ' ' + (location.y + size.height / 2);
1678
+ return appendShape(maps.renderer.drawPath(options), element);
1679
+ }
1680
+ /**
1681
+ * Internal rendering of Star
1682
+ *
1683
+ * @param {Maps} maps - Specifies the instance of the maps
1684
+ * @param {PathOption} options - Specifies the path options
1685
+ * @param {Size} size - Specifies the size
1686
+ * @param {MapLocation} location - Specifies the map location
1687
+ * @param {Element} element - Specifies the element
1688
+ * @returns {Element} - Returns the element
1689
+ * @private
1690
+ */
1691
+ export function drawStar(maps: Maps, options: PathOption, size: Size, location: MapLocation, element?: Element): Element {
1692
+ options.d = 'M ' + (location.x + size.width / 3) + ' ' + (location.y - size.height / 2) + ' L ' + (location.x - size.width / 2)
1693
+ + ' ' + (location.y + size.height / 6) + ' L ' + (location.x + size.width / 2) + ' ' + (location.y + size.height / 6) + ' L '
1694
+ + (location.x - size.width / 3) + ' ' + (location.y - size.height / 2) + ' L ' + location.x + ' ' + (location.y + size.height / 2)
1695
+ + ' L ' + (location.x + size.width / 3) + ' ' + (location.y - size.height / 2) + ' Z';
1696
+ return appendShape(maps.renderer.drawPath(options), element);
1697
+ }
1698
+ /**
1699
+ * Internal rendering of Balloon
1700
+ *
1701
+ * @param {Maps} maps - Specifies the instance of the maps
1702
+ * @param {PathOption} options - Specifies the path options
1703
+ * @param {Size} size - Specifies the size
1704
+ * @param {MapLocation} location - Specifies the map location
1705
+ * @param {Element} element - Specifies the element
1706
+ * @returns {Element} - Returns the element
1707
+ * @private
1708
+ */
1709
+ export function drawBalloon(maps: Maps, options: PathOption, size: Size, location: MapLocation, type: string, element?: Element): Element {
1710
+ const width: number = size.width;
1711
+ const height: number = size.height;
1712
+ let pathElement: Element;
1713
+ location.x -= width / 2;
1714
+ location.y -= height;
1715
+ options.d = 'M15,0C8.8,0,3.8,5,3.8,11.2C3.8,17.5,9.4,24.4,15,30c5.6-5.6,11.2-12.5,11.2-18.8C26.2,5,21.2,0,15,0z M15,16' +
1716
+ 'c-2.8,0-5-2.2-5-5s2.2-5,5-5s5,2.2,5,5S17.8,16,15,16z';
1717
+ const balloon: Element = maps.renderer.drawPath(options);
1718
+ const x: number = size.width / 30;
1719
+ const y: number = size.height / 30;
1720
+ balloon.setAttribute('transform', 'translate(' + location.x + ', ' + location.y + ') scale(' + x + ', ' + y + ')');
1721
+ if (type === 'Marker') {
1722
+ const g: Element = maps.renderer.createGroup({ id: options.id + '_Group' });
1723
+ appendShape(balloon, g);
1724
+ pathElement = appendShape(g, element);
1725
+ }
1726
+ else {
1727
+ pathElement = balloon;
1728
+ }
1729
+ return pathElement;
1730
+ }
1731
+ /**
1732
+ * Internal rendering of Pattern
1733
+ *
1734
+ * @param {Maps} maps - Specifies the instance of the maps
1735
+ * @param {PatternOptions} options - Specifies the pattern options
1736
+ * @param {Element[]} elements - Specifies the elements
1737
+ * @param {Element} element - Specifies the element
1738
+ * @returns {Element} - Returns the element
1739
+ * @private
1740
+ */
1741
+ export function drawPattern(maps: Maps, options: PatternOptions, elements: Element[], element?: Element): Element {
1742
+ const pattern: Element = maps.renderer.createPattern(options, 'pattern');
1743
+ for (const ele of elements) {
1744
+ appendShape(ele, pattern);
1745
+ }
1746
+ return appendShape(pattern, element);
1747
+ }
1748
+ /**
1749
+ * Method to get specific field and vaues from data.
1750
+ *
1751
+ * @param {any[]} dataSource - Specifies the data source
1752
+ * @param {string[]} fields - Specifies the fields
1753
+ * @returns {any[]} - Returns the object
1754
+ * @private
1755
+ */
1756
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1757
+ export function getFieldData(dataSource: any[], fields: string[]): any[] {
1758
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1759
+ const newData: any[] = [];
1760
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1761
+ let data: { [key: string]: any };
1762
+ for (const temp of dataSource) {
1763
+ data = {};
1764
+ for (const field of fields) {
1765
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1766
+ if ((<any>temp)[field]) {
1767
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1768
+ data[field] = (<any>temp)[field];
1769
+ }
1770
+ }
1771
+ newData.push(data);
1772
+ }
1773
+ return newData;
1774
+ }
1775
+ /**
1776
+ * To find the index of dataSource from shape properties
1777
+ *
1778
+ * @param {any[]} dataSource - Specifies the data source
1779
+ * @param {any} properties - Specifies the properties
1780
+ * @param {string} dataPath - Specifies the data path
1781
+ * @param {string | string[]} propertyPath - Specifies the property path
1782
+ * @param {LayerSettingsModel} layer - Specifies the layer settings
1783
+ * @returns {number} - Returns the number
1784
+ */
1785
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1786
+ export function checkShapeDataFields(dataSource: any[], properties: any, dataPath: string, propertyPath: string | string[],
1787
+ layer: LayerSettingsModel): number {
1788
+ if (!(isNullOrUndefined(properties))) {
1789
+ for (let i: number = 0; i < dataSource.length; i++) {
1790
+ const shapeDataPath: string = ((dataPath.indexOf('.') > -1) ? getValueFromObject(dataSource[i], dataPath) :
1791
+ dataSource[i][dataPath]);
1792
+ const shapePath: string = checkPropertyPath(shapeDataPath, propertyPath, properties);
1793
+ const shapeDataPathValue: string = !isNullOrUndefined(shapeDataPath) && isNaN(properties[shapePath])
1794
+ ? shapeDataPath.toLowerCase() : shapeDataPath;
1795
+ const propertiesShapePathValue: string = !isNullOrUndefined(properties[shapePath]) && isNaN(properties[shapePath])
1796
+ ? properties[shapePath].toLowerCase() : properties[shapePath];
1797
+ if (shapeDataPathValue === propertiesShapePathValue) {
1798
+ return i;
1799
+ }
1800
+ }
1801
+ }
1802
+ return null;
1803
+ }
1804
+ /**
1805
+ *
1806
+ * @param {string} shapeData - Specifies the shape data
1807
+ * @param {string | string[]} shapePropertyPath - Specifies the shape property path
1808
+ * @param {any} shape - Specifies the shape
1809
+ * @returns {string} - Returns the string value
1810
+ */
1811
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1812
+ export function checkPropertyPath(shapeData: string, shapePropertyPath: string | string[], shape: any): string {
1813
+ if (!isNullOrUndefined(shapeData) && !isNullOrUndefined(shape)) {
1814
+ if (!isNullOrUndefined(shapePropertyPath)) {
1815
+ let length: number;
1816
+ const properties: string[] = (Object.prototype.toString.call(shapePropertyPath) === '[object Array]' ?
1817
+ shapePropertyPath : [shapePropertyPath]) as string[];
1818
+ for (let i: number = 0; i < properties.length; i++) {
1819
+ const shapeDataValue: string = !isNullOrUndefined(shapeData) ? shapeData.toLowerCase() : shapeData;
1820
+ const shapePropertiesValue: string = !isNullOrUndefined(shape[properties[i]])
1821
+ && isNaN(shape[properties[i]])
1822
+ ? shape[properties[i]].toLowerCase() : shape[properties[i]];
1823
+ if (shapeDataValue === shapePropertiesValue) {
1824
+ return properties[i];
1825
+ }
1826
+ }
1827
+ }
1828
+ }
1829
+ return null;
1830
+ }
1831
+
1832
+ /**
1833
+ *
1834
+ * @param {MapLocation[]} points - Specifies the location
1835
+ * @param {number} start - Specifies the start value
1836
+ * @param {number} end - Specifies the end value
1837
+ * @returns {MapLocation[]} - Returns the location
1838
+ */
1839
+ export function filter(points: MapLocation[], start: number, end: number): MapLocation[] {
1840
+ const pointObject: MapLocation[] = [];
1841
+ for (let i: number = 0; i < points.length; i++) {
1842
+ const point: MapLocation = points[i];
1843
+ if (start <= point.y && end >= point.y) {
1844
+ pointObject.push(point);
1845
+ }
1846
+ }
1847
+ return pointObject;
1848
+ }
1849
+
1850
+ /**
1851
+ *
1852
+ * @param {number} min - Specifies the min value
1853
+ * @param {number} max - Specifies the max value
1854
+ * @param {number} value - Specifies the value
1855
+ * @param {number} minValue - Specifies the minValue
1856
+ * @param {number} maxValue -Specifies the maxValue
1857
+ * @returns {number} - Returns the number
1858
+ */
1859
+ export function getRatioOfBubble(min: number, max: number, value: number, minValue: number, maxValue: number): number {
1860
+ const percent: number = (100 / (maxValue - minValue)) * (value - minValue);
1861
+ let bubbleRadius: number = (((max - min) / 100) * percent) + min;
1862
+ if (maxValue === minValue) {
1863
+ bubbleRadius = (((max - min) / 100)) + min;
1864
+ }
1865
+ return bubbleRadius;
1866
+ }
1867
+ /**
1868
+ * To find the midpoint of the polygon from points
1869
+ *
1870
+ * @param {MapLocation[]} points - Specifies the points
1871
+ * @param {string} type - Specifies the type
1872
+ * @param {string} geometryType - Specified the type of the geometry
1873
+ * @returns {any} - Specifies the object
1874
+ */
1875
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1876
+ export function findMidPointOfPolygon(points: MapLocation[], type: string, geometryType?: string): any {
1877
+ if (!points.length) {
1878
+ return null;
1879
+ }
1880
+ const min: number = 0;
1881
+ const max: number = points.length;
1882
+ let startX: number;
1883
+ let startY: number;
1884
+ let startX1: number;
1885
+ let startY1: number;
1886
+ let sum: number = 0;
1887
+ let xSum: number = 0;
1888
+ let ySum: number = 0;
1889
+
1890
+ for (let i: number = min; i <= max - 1; i++) {
1891
+ startX = points[i].x;
1892
+ startY = type === 'Mercator' || geometryType === 'Normal' ? points[i].y : -(points[i].y);
1893
+ if (i === max - 1) {
1894
+ startX1 = points[0].x;
1895
+ startY1 = type === 'Mercator' || geometryType === 'Normal' ? points[0].y : -(points[0].y);
1896
+ } else {
1897
+ startX1 = points[i + 1].x;
1898
+ startY1 = type === 'Mercator' || geometryType === 'Normal' ? points[i + 1].y : -(points[i + 1].y);
1899
+ }
1900
+ sum = sum + Math.abs(((startX * startY1)) - (startX1 * startY));
1901
+ xSum = xSum + Math.abs(((startX + startX1) * (((startX * startY1) - (startX1 * startY)))));
1902
+ ySum = ySum + Math.abs(((startY + startY1) * (((startX * startY1) - (startX1 * startY)))));
1903
+ }
1904
+ sum = 0.5 * sum;
1905
+ xSum = (1 / (4 * sum)) * xSum;
1906
+ ySum = (1 / (4 * sum)) * ySum;
1907
+
1908
+ /* Code for finding nearest points in polygon related to midPoint*/
1909
+ let rightMinPoint: MapLocation = { x: 0, y: 0 };
1910
+ let rightMaxPoint: MapLocation = { x: 0, y: 0 };
1911
+ let leftMinPoint: MapLocation = { x: 0, y: 0 };
1912
+ let leftMaxPoint: MapLocation = { x: 0, y: 0 };
1913
+ let bottomMinPoint: MapLocation = { x: 0, y: 0 };
1914
+ let bottomMaxPoint: MapLocation = { x: 0, y: 0 };
1915
+ let topMinPoint: MapLocation = { x: 0, y: 0 };
1916
+ let topMaxPoint: MapLocation = { x: 0, y: 0 };
1917
+ let height: number = 0;
1918
+ for (let i: number = min; i <= max - 1; i++) {
1919
+ const point: MapLocation = points[i];
1920
+ point.y = type === 'Mercator' || geometryType === 'Normal' ? point.y : -(point.y);
1921
+ if (point.y > ySum) {
1922
+ if (point.x < xSum && xSum - point.x < xSum - bottomMinPoint.x) {
1923
+ bottomMinPoint = { x: point.x, y: point.y };
1924
+ } else if (point.x > xSum && (bottomMaxPoint.x === 0 || point.x - xSum < bottomMaxPoint.x - xSum)) {
1925
+ bottomMaxPoint = { x: point.x, y: point.y };
1926
+ }
1927
+ } else {
1928
+ if (point.x < xSum && xSum - point.x < xSum - topMinPoint.x) {
1929
+ topMinPoint = { x: point.x, y: point.y };
1930
+ } else if (point.x > xSum && (topMaxPoint.x === 0 || point.x - xSum < topMaxPoint.x - xSum)) {
1931
+ topMaxPoint = { x: point.x, y: point.y };
1932
+ }
1933
+ }
1934
+ height = (bottomMaxPoint.y - topMaxPoint.y) + ((bottomMaxPoint.y - topMaxPoint.y) / 4);
1935
+ if (point.x > xSum) {
1936
+ if (point.y < ySum && ySum - point.y < ySum - rightMinPoint.y) {
1937
+ rightMinPoint = { x: point.x, y: point.y };
1938
+ } else if (point.y > ySum && (rightMaxPoint.y === 0 || point.y - ySum < rightMaxPoint.y - ySum)) {
1939
+ rightMaxPoint = { x: point.x, y: point.y };
1940
+ }
1941
+ } else {
1942
+ if (point.y < ySum && ySum - point.y < ySum - leftMinPoint.y) {
1943
+ leftMinPoint = { x: point.x, y: point.y };
1944
+ } else if (point.y > ySum && (leftMaxPoint.y === 0 || point.y - ySum < leftMaxPoint.y - ySum)) {
1945
+ leftMaxPoint = { x: point.x, y: point.y };
1946
+ }
1947
+ }
1948
+ }
1949
+
1950
+ return {
1951
+ x: xSum, y: ySum, rightMin: rightMinPoint, rightMax: rightMaxPoint,
1952
+ leftMin: leftMinPoint, leftMax: leftMaxPoint, points: points, topMax: topMaxPoint, topMin: topMinPoint,
1953
+ bottomMax: bottomMaxPoint, bottomMin: bottomMinPoint, height: height
1954
+ };
1955
+ }
1956
+ /**
1957
+ * Check custom path
1958
+ *
1959
+ * @param {any[]} layerData - Specifies the layer data
1960
+ * @returns {boolean} - Returns the boolean vlue
1961
+ * @private
1962
+ */
1963
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1964
+ export function isCustomPath(layerData: any[]): boolean {
1965
+ let customPath: boolean = false;
1966
+ if (Object.prototype.toString.call(layerData) === '[object Array]') {
1967
+ Array.prototype.forEach.call(layerData, (layer: LayerSettings, index: number) => {
1968
+ if (!isNullOrUndefined(layer['geometry']) && layer['geometry']['type'] === 'Path') {
1969
+ customPath = true;
1970
+ }
1971
+ });
1972
+ }
1973
+ return customPath;
1974
+ }
1975
+
1976
+ /**
1977
+ * Trim the title text
1978
+ *
1979
+ * @param {number} maxWidth - Specifies the maximum width
1980
+ * @param {string} text - Specifies the text
1981
+ * @param {FontModel} font - Specifies the font
1982
+ * @returns {string} - Returns the string
1983
+ * @private
1984
+ */
1985
+ export function textTrim(maxWidth: number, text: string, font: FontModel): string {
1986
+ let label: string = text;
1987
+ let size: number = measureText(text, font).width;
1988
+ if (size > maxWidth) {
1989
+ const textLength: number = text.length;
1990
+ for (let i: number = textLength - 1; i >= 0; --i) {
1991
+ label = text.substring(0, i) + '...';
1992
+ size = measureText(label, font).width;
1993
+ if (size <= maxWidth || label.length < 4) {
1994
+ if (label.length < 4) {
1995
+ label = ' ';
1996
+ }
1997
+ return label;
1998
+ }
1999
+ }
2000
+ }
2001
+ return label;
2002
+ }
2003
+
2004
+ /**
2005
+ * Method to calculate x position of title
2006
+ *
2007
+ * @param {Rect} location - Specifies the location
2008
+ * @param {Alignment} alignment - Specifies the alignment
2009
+ * @param {Size} textSize - Specifies the text size
2010
+ * @param {string} type - Specifies the type
2011
+ * @returns {Point} - Returns the point values
2012
+ */
2013
+ export function findPosition(location: Rect, alignment: Alignment, textSize: Size, type: string): Point {
2014
+ let x: number;
2015
+ switch (alignment) {
2016
+ case 'Near':
2017
+ x = location.x;
2018
+ break;
2019
+ case 'Center':
2020
+ x = (type === 'title') ? (location.width / 2 - textSize.width / 2) :
2021
+ ((location.x + (location.width / 2)) - textSize.width / 2);
2022
+ break;
2023
+ case 'Far':
2024
+ x = (type === 'title') ? (location.width - location.y - textSize.width) :
2025
+ ((location.x + location.width) - textSize.width);
2026
+ break;
2027
+ }
2028
+ const y: number = (type === 'title') ? location.y + (textSize.height / 2) : ((location.y + location.height / 2) + textSize.height / 2);
2029
+ return new Point(x, y);
2030
+ }
2031
+ /**
2032
+ * To remove element by id
2033
+ *
2034
+ * @param {string} id - Specifies the id
2035
+ * @returns {void}
2036
+ */
2037
+ export function removeElement(id: string): void {
2038
+ const element: Element = document.getElementById(id);
2039
+ return element ? remove(element) : null;
2040
+ }
2041
+
2042
+ /**
2043
+ * To calculate map center position from pixel values
2044
+ *
2045
+ * @param {Maps} mapObject - Specifies the map object
2046
+ * @param {LayerSettings} layer - Specifies the layer settings
2047
+ * @returns {Point} - Returns the x and y points
2048
+ */
2049
+ export function calculateCenterFromPixel(mapObject: Maps, layer: LayerSettings): Point {
2050
+ const point1: Point = convertGeoToPoint(
2051
+ mapObject.minLatOfGivenLocation, mapObject.minLongOfGivenLocation, mapObject.mapLayerPanel.calculateFactor(layer), layer, mapObject);
2052
+ const point2: Point = convertGeoToPoint(
2053
+ mapObject.maxLatOfGivenLocation, mapObject.maxLongOfGivenLocation, mapObject.mapLayerPanel.calculateFactor(layer), layer, mapObject);
2054
+ const x: number = (point1.x + point2.x) / 2;
2055
+ const y: number = (point1.y + point2.y) / 2;
2056
+ return new Point(x, y);
2057
+ }
2058
+
2059
+ /**
2060
+ * @param {Maps} mapObject - Specifies the map object
2061
+ * @param {LayerSettings} layer - Specifies the layer settings
2062
+ * @param {boolean} animate - Specifies the boolean value
2063
+ * @returns {any} - Returns the object
2064
+ * @private
2065
+ */
2066
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2067
+ export function getTranslate(mapObject: Maps, layer: LayerSettings, animate?: boolean): any {
2068
+ let zoomFactorValue: number = mapObject.zoomSettings.zoomFactor; let scaleFactor: number;
2069
+ let center: CenterPositionModel = mapObject.centerPosition;
2070
+ let centerLatitude: number = center.latitude;
2071
+ let centerLongitude: number = center.longitude;
2072
+ const checkMethodeZoom: boolean = !isNullOrUndefined(mapObject.centerLatOfGivenLocation) &&
2073
+ !isNullOrUndefined(mapObject.centerLongOfGivenLocation) && mapObject.zoomNotApplied;
2074
+ if (isNullOrUndefined(mapObject.mapScaleValue)) {
2075
+ mapObject.mapScaleValue = zoomFactorValue;
2076
+ }
2077
+ if (mapObject.zoomSettings.shouldZoomInitially && mapObject.zoomSettings.enable) {
2078
+ mapObject.mapScaleValue = scaleFactor = zoomFactorValue = ((mapObject.zoomSettings.shouldZoomInitially || mapObject.enablePersistence) && mapObject.scale === 1)
2079
+ ? mapObject.scale : (isNullOrUndefined(mapObject.markerZoomFactor)) ? 1 : mapObject.markerZoomFactor;
2080
+ if (mapObject.mapScaleValue !== mapObject.markerZoomFactor && !mapObject.enablePersistence) {
2081
+ mapObject.mapScaleValue = zoomFactorValue = mapObject.markerZoomFactor;
2082
+ }
2083
+ if (!isNullOrUndefined(mapObject.markerCenterLatitude) && !isNullOrUndefined(mapObject.markerCenterLongitude)) {
2084
+ centerLatitude = mapObject.markerCenterLatitude;
2085
+ centerLongitude = mapObject.markerCenterLongitude;
2086
+ }
2087
+ }
2088
+ if (checkMethodeZoom) {
2089
+ mapObject.mapScaleValue = scaleFactor = zoomFactorValue = mapObject.scaleOfGivenLocation;
2090
+ }
2091
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2092
+ const min: any = !isNullOrUndefined(mapObject.baseMapRectBounds) ? mapObject.baseMapRectBounds['min'] as any : null;
2093
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2094
+ const max: any = !isNullOrUndefined(mapObject.baseMapRectBounds) ? mapObject.baseMapRectBounds['max'] as any : null;
2095
+ const zoomFactor: number = animate ? 1 : mapObject.mapScaleValue;
2096
+ if (isNullOrUndefined(mapObject.currentShapeDataLength)) {
2097
+ mapObject.currentShapeDataLength = !isNullOrUndefined(layer.shapeData['features'])
2098
+ ? layer.shapeData['features'].length : layer.shapeData['geometries'].length;
2099
+ }
2100
+ const size: Rect = (mapObject.totalRect && mapObject.legendSettings.visible) ? mapObject.totalRect : mapObject.mapAreaRect;
2101
+ const availSize: Size = mapObject.availableSize;
2102
+ let x: number; let y: number;
2103
+ if (!isNullOrUndefined(min) && !isNullOrUndefined(max)) {
2104
+ let mapWidth: number = Math.abs(max['x'] - min['x']);
2105
+ let mapHeight: number = Math.abs(min['y'] - max['y']);
2106
+ const factor: number = animate ? 1 : mapObject.markerZoomFactor === 1 ? mapObject.mapScaleValue : zoomFactorValue;
2107
+ center = mapObject.zoomSettings.shouldZoomInitially
2108
+ && mapObject.markerZoomedState && !mapObject.zoomPersistence ? mapObject.markerZoomCenterPoint :
2109
+ mapObject.centerPosition;
2110
+ if ((!isNullOrUndefined(centerLongitude) && !isNullOrUndefined(centerLatitude)) || checkMethodeZoom) {
2111
+ const leftPosition: number = (((mapWidth + Math.abs(mapObject.mapAreaRect.width - mapWidth)) / 2) + mapObject.mapAreaRect.x) / factor;
2112
+ const topPosition: number = (((mapHeight + Math.abs(mapObject.mapAreaRect.height - mapHeight)) / 2) + mapObject.mapAreaRect.y) / factor;
2113
+ const point: Point = checkMethodeZoom ? calculateCenterFromPixel(mapObject, layer) :
2114
+ convertGeoToPoint(
2115
+ centerLatitude, centerLongitude, mapObject.mapLayerPanel.calculateFactor(layer), layer, mapObject);
2116
+ if (isNullOrUndefined(mapObject.previousProjection) || mapObject.previousProjection !== mapObject.projectionType) {
2117
+ x = -point.x + leftPosition;
2118
+ y = -point.y + topPosition;
2119
+ scaleFactor = zoomFactor;
2120
+ } else {
2121
+ if (Math.floor(mapObject.scale) !== 1 && mapObject.zoomSettings.shouldZoomInitially || (mapObject.zoomNotApplied)) {
2122
+ x = -point.x + leftPosition;
2123
+ y = -point.y + topPosition;
2124
+ } else {
2125
+ if (mapObject.zoomSettings.shouldZoomInitially || mapObject.zoomNotApplied) {
2126
+ x = -point.x + leftPosition;
2127
+ y = -point.y + topPosition;
2128
+ scaleFactor = zoomFactor;
2129
+ } else {
2130
+ x = mapObject.zoomTranslatePoint.x;
2131
+ y = mapObject.zoomTranslatePoint.y;
2132
+ }
2133
+ }
2134
+ scaleFactor = mapObject.mapScaleValue;
2135
+ }
2136
+ } else {
2137
+ if (isNullOrUndefined(mapObject.previousProjection) || mapObject.previousProjection !== mapObject.projectionType) {
2138
+ if (mapHeight === 0 || mapWidth === 0 || mapHeight === mapWidth) {
2139
+ mapWidth = size.width / 2;
2140
+ mapHeight = size.height;
2141
+ }
2142
+ scaleFactor = parseFloat(Math.min(size.width / mapWidth, size.height / mapHeight).toFixed(2));
2143
+ scaleFactor = scaleFactor > 1.05 ? 1 : scaleFactor;
2144
+ mapWidth *= scaleFactor;
2145
+ mapHeight *= scaleFactor;
2146
+ const widthDiff: number = min['x'] !== 0 && mapObject.translateType === 'layers' ? availSize.width - size.width : 0;
2147
+ x = size.x + ((-(min['x'])) + ((size.width / 2) - (mapWidth / 2))) - widthDiff;
2148
+ y = size.y + ((-(min['y'])) + ((size.height / 2) - (mapHeight / 2)));
2149
+ mapObject.previousTranslate = new Point(x, y);
2150
+ } else {
2151
+ if (!mapObject.zoomSettings.shouldZoomInitially && mapObject.markerZoomFactor === 1 && mapObject.mapScaleValue === 1) {
2152
+ scaleFactor = parseFloat(Math.min(size.width / mapWidth, size.height / mapHeight).toFixed(2));
2153
+ mapHeight *= scaleFactor; mapWidth *= scaleFactor;
2154
+ y = size.y + ((-(min['y'])) + ((size.height / 2) - (mapHeight / 2)));
2155
+ x = size.x + ((-(min['x'])) + ((size.width / 2) - (mapWidth / 2)));
2156
+ } else {
2157
+ scaleFactor = mapObject.mapScaleValue < 1 ? mapObject.mapScaleValue + 1 : mapObject.mapScaleValue;
2158
+ mapObject.mapScaleValue = mapObject.zoomSettings.enable && mapObject.mapScaleValue !== 1 ? mapObject.mapScaleValue : 1;
2159
+ if ((mapObject.currentShapeDataLength !== (!isNullOrUndefined(layer.shapeData['features'])
2160
+ ? layer.shapeData['features'].length : layer.shapeData['geometries'].length)) && layer.type !== 'SubLayer') {
2161
+ const scale: number = parseFloat(Math.min(size.height / mapHeight, size.width / mapWidth).toFixed(2));
2162
+ mapHeight *= scale; mapWidth *= scale;
2163
+ y = size.y + ((-(min['y'])) + ((size.height / 2)
2164
+ - (mapHeight / 2)));
2165
+ scaleFactor = scale;
2166
+ x = size.x + ((-(min['x']))
2167
+ + ((size.width / 2) - (mapWidth / 2)));
2168
+ } else if (mapObject.availableSize.height !== mapObject.heightBeforeRefresh || mapObject.widthBeforeRefresh !== mapObject.availableSize.width) {
2169
+ const cscaleFactor: number = parseFloat(Math.min(size.width / mapWidth, size.height / mapHeight).toFixed(2));
2170
+ let cmapWidth: number = mapWidth; cmapWidth *= cscaleFactor;
2171
+ let cmapHeight: number = mapHeight; cmapHeight *= cscaleFactor;
2172
+ const x1: number = size.x + ((-(min['x'])) + ((size.width / 2) - (cmapWidth / 2)));
2173
+ const y1: number = size.y + ((-(min['y'])) + ((size.height / 2) - (cmapHeight / 2)));
2174
+ const xdiff: number = (mapObject.translatePoint.x - mapObject.previousTranslate.x) / (mapObject.widthBeforeRefresh);
2175
+ const ydiff: number = (mapObject.translatePoint.y - mapObject.previousTranslate.y) / (mapObject.heightBeforeRefresh);
2176
+ const actxdiff: number = xdiff * (mapObject.availableSize.width);
2177
+ const actydiff: number = ydiff * (mapObject.availableSize.height);
2178
+ x = x1 + actxdiff;
2179
+ y = y1 + actydiff;
2180
+ mapObject.previousTranslate = new Point(x1, y1);
2181
+ mapObject.zoomTranslatePoint.x = x;
2182
+ mapObject.zoomTranslatePoint.y = y;
2183
+ } else {
2184
+ if (!isNullOrUndefined(mapObject.previousProjection) && (mapObject.mapScaleValue === 1 || mapObject.mapScaleValue <= 1.05) && !mapObject.zoomModule.isDragZoom) {
2185
+ scaleFactor = parseFloat(Math.min(size.width / mapWidth, size.height / mapHeight).toFixed(2));
2186
+ scaleFactor = scaleFactor > 1.05 ? 1: scaleFactor;
2187
+ mapWidth *= scaleFactor;
2188
+ x = size.x + ((-(min['x'])) + ((size.width / 2) - (mapWidth / 2)));
2189
+ mapHeight *= scaleFactor;
2190
+ y = size.y + ((-(min['y'])) + ((size.height / 2) - (mapHeight / 2)));
2191
+ } else {
2192
+ x = mapObject.zoomTranslatePoint.x;
2193
+ y = mapObject.zoomTranslatePoint.y;
2194
+ scaleFactor = mapObject.scale;
2195
+ }
2196
+ }
2197
+ }
2198
+ }
2199
+ }
2200
+ if (!isNullOrUndefined(mapObject.translatePoint)) {
2201
+ x = (mapObject.enablePersistence && mapObject.translatePoint.x !== 0 && !mapObject.zoomNotApplied) ? mapObject.translatePoint.x : x;
2202
+ y = (mapObject.enablePersistence && mapObject.translatePoint.y !== 0 && !mapObject.zoomNotApplied) ? mapObject.translatePoint.y : y;
2203
+ }
2204
+ }
2205
+ scaleFactor = (mapObject.enablePersistence) ? ((mapObject.mapScaleValue >= 1) ? mapObject.mapScaleValue : 1) : scaleFactor;
2206
+ mapObject.widthBeforeRefresh = mapObject.availableSize.width;
2207
+ mapObject.heightBeforeRefresh = mapObject.availableSize.height;
2208
+ return { scale: scaleFactor, location: new Point(x, y) };
2209
+ }
2210
+
2211
+ /**
2212
+ * @param {Maps} mapObject - Specifies the map object
2213
+ * @param {LayerSettings} layer - Specifies the layer
2214
+ * @param {boolean} animate - Specifies the boolean value
2215
+ * @returns {any} - Returns the object.
2216
+ * @private
2217
+ */
2218
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2219
+ export function getZoomTranslate(mapObject: Maps, layer: LayerSettings, animate?: boolean): any {
2220
+ let zoomFactorValue: number = mapObject.zoomSettings.zoomFactor;
2221
+ let scaleFactor: number;
2222
+ const center: CenterPositionModel = mapObject.centerPosition;
2223
+ let latitude: number = center.latitude;
2224
+ let longitude: number = center.longitude;
2225
+ const checkZoomMethod: boolean = !isNullOrUndefined(mapObject.centerLongOfGivenLocation) &&
2226
+ !isNullOrUndefined(mapObject.centerLatOfGivenLocation) && mapObject.zoomNotApplied;
2227
+ if (isNullOrUndefined(mapObject.previousCenterLatitude) &&
2228
+ isNullOrUndefined(mapObject.previousCenterLongitude)) {
2229
+ mapObject.previousCenterLatitude = mapObject.centerPosition.latitude;
2230
+ mapObject.previousCenterLongitude = mapObject.centerPosition.longitude;
2231
+ }
2232
+ else if (mapObject.previousCenterLatitude !==
2233
+ mapObject.centerPosition.latitude && mapObject.previousCenterLongitude !==
2234
+ mapObject.centerPosition.longitude) {
2235
+ mapObject.centerPositionChanged = true;
2236
+ mapObject.previousCenterLatitude = mapObject.centerPosition.latitude;
2237
+ mapObject.previousCenterLongitude = mapObject.centerPosition.longitude;
2238
+ }
2239
+ else {
2240
+ mapObject.centerPositionChanged = false;
2241
+ }
2242
+ if (isNullOrUndefined(mapObject.mapScaleValue) || (zoomFactorValue > mapObject.mapScaleValue)) {
2243
+ if (mapObject.isReset && mapObject.mapScaleValue === 1) {
2244
+ // eslint-disable-next-line no-self-assign
2245
+ mapObject.mapScaleValue = mapObject.mapScaleValue;
2246
+ } else {
2247
+ mapObject.mapScaleValue = zoomFactorValue;
2248
+ }
2249
+ }
2250
+ mapObject.mapScaleValue = mapObject.zoomSettings.zoomFactor !== 1 &&
2251
+ mapObject.zoomSettings.zoomFactor ===
2252
+ mapObject.mapScaleValue ? mapObject.zoomSettings.zoomFactor :
2253
+ mapObject.zoomSettings.zoomFactor !== mapObject.mapScaleValue && !mapObject.centerPositionChanged ? mapObject.mapScaleValue : mapObject.zoomSettings.zoomFactor;
2254
+ if (mapObject.zoomSettings.shouldZoomInitially) {
2255
+ mapObject.mapScaleValue = zoomFactorValue = scaleFactor = ((mapObject.enablePersistence || mapObject.zoomSettings.shouldZoomInitially) && mapObject.scale === 1)
2256
+ ? mapObject.scale : (isNullOrUndefined(mapObject.markerZoomFactor)) ? mapObject.mapScaleValue : mapObject.markerZoomFactor;
2257
+ zoomFactorValue = mapObject.mapScaleValue;
2258
+ if (!isNullOrUndefined(mapObject.markerCenterLatitude) && !isNullOrUndefined(mapObject.markerCenterLongitude)) {
2259
+ latitude = mapObject.markerCenterLatitude;
2260
+ longitude = mapObject.markerCenterLongitude;
2261
+ }
2262
+ }
2263
+ if (checkZoomMethod) {
2264
+ mapObject.mapScaleValue = scaleFactor = zoomFactorValue = mapObject.scaleOfGivenLocation;
2265
+ }
2266
+ const zoomFactor: number = animate ? 1 : mapObject.mapScaleValue;
2267
+ const size: Rect = mapObject.mapAreaRect; let x: number; let y: number;
2268
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2269
+ const min: any = mapObject.baseMapRectBounds['min'] as any;
2270
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2271
+ const max: any = mapObject.baseMapRectBounds['max'] as any;
2272
+ const factor: number = animate ? 1 : mapObject.mapScaleValue;
2273
+ const mapWidth: number = Math.abs(max['x'] - min['x']); const mapHeight: number = Math.abs(min['y'] - max['y']);
2274
+ if ((!isNullOrUndefined(longitude) && !isNullOrUndefined(latitude)) || checkZoomMethod) {
2275
+ const topPosition: number = ((mapHeight + Math.abs(mapObject.mapAreaRect.height - mapHeight)) / 2) / factor;
2276
+ const leftPosition: number = ((mapWidth + Math.abs(mapObject.mapAreaRect.width - mapWidth)) / 2) / factor;
2277
+ const point: Point = checkZoomMethod ? calculateCenterFromPixel(mapObject, layer) :
2278
+ convertGeoToPoint(
2279
+ latitude, longitude, mapObject.mapLayerPanel.calculateFactor(layer), layer, mapObject);
2280
+ if ((!isNullOrUndefined(mapObject.zoomTranslatePoint) || !isNullOrUndefined(mapObject.previousProjection)) && !mapObject.zoomNotApplied) {
2281
+ if (mapObject.previousProjection !== mapObject.projectionType) {
2282
+ x = -point.x + leftPosition;
2283
+ y = -point.y + topPosition;
2284
+ } else {
2285
+ x = mapObject.zoomTranslatePoint.x;
2286
+ y = mapObject.zoomTranslatePoint.y;
2287
+ zoomFactorValue = zoomFactor;
2288
+ }
2289
+ } else {
2290
+ x = -point.x + leftPosition + mapObject.mapAreaRect.x / zoomFactor;
2291
+ y = -point.y + topPosition + mapObject.mapAreaRect.y / zoomFactor;
2292
+ }
2293
+ if (!isNullOrUndefined(mapObject.translatePoint)) {
2294
+ y = (mapObject.enablePersistence && mapObject.translatePoint.y !== 0 && !mapObject.zoomNotApplied) ? mapObject.translatePoint.y : y;
2295
+ x = (mapObject.enablePersistence && mapObject.translatePoint.x !== 0 && !mapObject.zoomNotApplied) ? mapObject.translatePoint.x : x;
2296
+ }
2297
+ scaleFactor = zoomFactorValue !== 0 ? zoomFactorValue : 1;
2298
+ } else {
2299
+ let zoomFact: number = mapObject.zoomSettings.zoomFactor === 0 ? 1 : mapObject.zoomSettings.zoomFactor;
2300
+ const maxZoomFact: number = mapObject.zoomSettings.maxZoom;
2301
+ zoomFact = zoomFact > maxZoomFact ? maxZoomFact : zoomFact;
2302
+ scaleFactor = zoomFact;
2303
+ const mapScale: number = mapObject.mapScaleValue === 0 ? 1 : mapObject.mapScaleValue > maxZoomFact
2304
+ ? maxZoomFact : mapObject.mapScaleValue;
2305
+ let leftPosition: number = (size.x + ((-(min['x'])) + ((size.width / 2) - (mapWidth / 2))));
2306
+ let topPosition: number = (size.y + ((-(min['y'])) + ((size.height / 2) - (mapHeight / 2))));
2307
+ if (!isNullOrUndefined(mapObject.zoomTranslatePoint) || !isNullOrUndefined(mapObject.previousProjection)) {
2308
+ if (mapObject.previousProjection !== mapObject.projectionType) {
2309
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2310
+ const previousPositions: any[] = [];
2311
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2312
+ let previousPoints: any = { x: leftPosition, y: topPosition };
2313
+ previousPositions.push(previousPoints);
2314
+ for (let i: number = 1; i < maxZoomFact; i++) {
2315
+ const translatePointX: number = previousPositions[i - 1]['x'] - (((size.width / (i)) - (size.width / (i + 1))) / 2);
2316
+ const translatePointY: number = previousPositions[i - 1]['y'] - (((size.height / (i)) - (size.height / (i + 1))) / 2);
2317
+ previousPoints = { x: translatePointX, y: translatePointY };
2318
+ previousPositions.push(previousPoints);
2319
+ }
2320
+ leftPosition = previousPositions[zoomFact - 1]['x'];
2321
+ topPosition = previousPositions[zoomFact - 1]['y'];
2322
+ } else {
2323
+ leftPosition = mapObject.zoomTranslatePoint.x;
2324
+ topPosition = mapObject.zoomTranslatePoint.y;
2325
+ if (zoomFact !== mapScale) {
2326
+ scaleFactor = mapScale;
2327
+ }
2328
+ }
2329
+ }
2330
+ if (!isNullOrUndefined(mapObject.translatePoint)) {
2331
+ x = (mapObject.enablePersistence && mapObject.translatePoint.x !== 0 && !mapObject.zoomNotApplied) ? mapObject.translatePoint.x : leftPosition;
2332
+ y = (mapObject.enablePersistence && mapObject.translatePoint.y !== 0 && !mapObject.zoomNotApplied) ? mapObject.translatePoint.y : topPosition;
2333
+ }
2334
+ }
2335
+ scaleFactor = (mapObject.enablePersistence) ? (mapObject.mapScaleValue === 0 ? 1 : mapObject.mapScaleValue) : scaleFactor;
2336
+ mapObject.widthBeforeRefresh = mapObject.availableSize.width;
2337
+ mapObject.heightBeforeRefresh = mapObject.availableSize.height;
2338
+ return { scale: animate ? 1 : scaleFactor, location: new Point(x, y) };
2339
+ }
2340
+
2341
+ /**
2342
+ * To get the html element by specified id
2343
+ *
2344
+ * @param {Maps} map - Specifies the instance of the maps
2345
+ * @returns {void}
2346
+ */
2347
+ export function fixInitialScaleForTile(map: Maps): void {
2348
+ map.tileZoomScale = map.tileZoomLevel = Math.floor(map.availableSize.height / 512) + 1;
2349
+ const padding: number = map.layers[map.baseLayerIndex].layerType !== 'GoogleStaticMap' ?
2350
+ 20 : 0;
2351
+ const totalSize: number = Math.pow(2, map.tileZoomLevel) * 256;
2352
+ map.tileTranslatePoint.x = (map.availableSize.width / 2) - (totalSize / 2);
2353
+ map.tileTranslatePoint.y = (map.availableSize.height / 2) - (totalSize / 2) + padding;
2354
+ map.previousTileWidth = map.availableSize.width;
2355
+ map.previousTileHeight = map.availableSize.height;
2356
+ }
2357
+
2358
+ /**
2359
+ * To get the html element by specified id
2360
+ *
2361
+ * @param {string} id - Specifies the id
2362
+ * @returns {Element} - Returns the element
2363
+ */
2364
+ export function getElementByID(id: string): Element {
2365
+ return document.getElementById(id);
2366
+ }
2367
+ /**
2368
+ * Function to get clientElement from id.
2369
+ *
2370
+ * @param {string} id - Specifies the id
2371
+ * @returns {Element} - Returns the element
2372
+ * @private
2373
+ */
2374
+ export function getClientElement(id: string): ClientRect {
2375
+ const element: HTMLElement = document.getElementById(id);
2376
+ if (!isNullOrUndefined(element)) {
2377
+ return element.getClientRects()[0];
2378
+ } else {
2379
+ return null;
2380
+ }
2381
+ }
2382
+ /**
2383
+ * To apply internalization
2384
+ *
2385
+ * @param {Maps} maps - Specifies the instance of the maps
2386
+ * @param {number} value - Specifies the value
2387
+ * @returns {string} - Returns the string
2388
+ */
2389
+ export function Internalize(maps: Maps, value: number): string {
2390
+ maps.formatFunction =
2391
+ maps.intl.getNumberFormat({ format: maps.format, useGrouping: maps.useGroupingSeparator });
2392
+ return maps.formatFunction(value);
2393
+ }
2394
+
2395
+ /**
2396
+ * Function to compile the template function for maps.
2397
+ *
2398
+ * @param {string} template - Specifies the template
2399
+ * @returns {Function} - Returns the function
2400
+ * @private
2401
+ */
2402
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2403
+ export function getTemplateFunction(template: string, maps: Maps): any {
2404
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2405
+ let templateFn: any = null;
2406
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2407
+ let e: any;
2408
+ try {
2409
+ if (document.querySelectorAll(template).length) {
2410
+ templateFn = templateComplier(document.querySelector(template).innerHTML.trim());
2411
+ } else if ((maps as any).isVue || (maps as any).isVue3) {
2412
+ templateFn = templateComplier(template);
2413
+ }
2414
+ } catch (e) {
2415
+ templateFn = templateComplier(template);
2416
+ }
2417
+ return templateFn;
2418
+ }
2419
+ /**
2420
+ * Function to get element from id.
2421
+ *
2422
+ * @param {string} id - Specifies the id
2423
+ * @returns {Element} - Returns the element
2424
+ * @private
2425
+ */
2426
+ export function getElement(id: string): Element {
2427
+ return document.getElementById(id);
2428
+ }
2429
+
2430
+ /**
2431
+ * Function to get shape data using target id
2432
+ *
2433
+ * @param {string} targetId - Specifies the target id
2434
+ * @param {Maps} map - Specifies the instance of the maps
2435
+ * @returns {any} - Returns the object
2436
+ */
2437
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2438
+ export function getShapeData(targetId: string, map: Maps): { shapeData: any, data: any } {
2439
+ const layerIndex: number = parseInt(targetId.split('_LayerIndex_')[1].split('_')[0], 10);
2440
+ const shapeIndex: number = parseInt(targetId.split('_shapeIndex_')[1].split('_')[0], 10);
2441
+ const layer: LayerSettings = map.layersCollection[layerIndex] as LayerSettings;
2442
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2443
+ const shapeData: any = layer.layerData[shapeIndex]['property'];
2444
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2445
+ let data: any;
2446
+ if (layer.dataSource) {
2447
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2448
+ data = layer.dataSource[checkShapeDataFields(<any[]>layer.dataSource, shapeData, layer.shapeDataPath, layer.shapePropertyPath,
2449
+ layer)];
2450
+ }
2451
+ return { shapeData: shapeData, data: data };
2452
+ }
2453
+ /**
2454
+ * Function to trigger shapeSelected event
2455
+ *
2456
+ * @param {string} targetId - Specifies the target id
2457
+ * @param {SelectionSettingsModel} selection - Specifies the selection
2458
+ * @param {Maps} maps - Specifies the instance of the maps
2459
+ * @param {string} eventName - Specifies the event name
2460
+ * @returns {IShapeSelectedEventArgs} - Returns the event args
2461
+ * @private
2462
+ */
2463
+ export function triggerShapeEvent(
2464
+ targetId: string, selection: SelectionSettingsModel, maps: Maps, eventName: string
2465
+ ): IShapeSelectedEventArgs {
2466
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2467
+ const shape: { shapeData: any, data: any } = getShapeData(targetId, maps);
2468
+ const border: BorderModel = {
2469
+ color: selection.border.color, opacity: selection.border.opacity,
2470
+ width: selection.border.width
2471
+ };
2472
+ const eventArgs: IShapeSelectedEventArgs = (selection.enableMultiSelect) ? {
2473
+ cancel: false,
2474
+ name: eventName,
2475
+ fill: selection.fill,
2476
+ opacity: selection.opacity,
2477
+ border: border,
2478
+ shapeData: shape.shapeData,
2479
+ data: shape.data,
2480
+ target: targetId,
2481
+ maps: maps,
2482
+ shapeDataCollection: maps.shapeSelectionItem
2483
+ } : {
2484
+ cancel: false,
2485
+ name: eventName,
2486
+ fill: selection.fill,
2487
+ opacity: selection.opacity,
2488
+ border: border,
2489
+ shapeData: shape.shapeData,
2490
+ data: shape.data,
2491
+ target: targetId,
2492
+ maps: maps
2493
+ };
2494
+ maps.trigger(eventName, eventArgs, (observedArgs: IShapeSelectedEventArgs) => {
2495
+ eventArgs.border.opacity = isNullOrUndefined(eventArgs.border.opacity) ? eventArgs.opacity : eventArgs.border.opacity;
2496
+ });
2497
+ return eventArgs;
2498
+ }
2499
+
2500
+ /**
2501
+ * Function to get elements using class name
2502
+ *
2503
+ * @param {string} className - Specifies the class name
2504
+ * @returns {HTMLCollectionOf<Element>} - Returns the collection
2505
+ */
2506
+ export function getElementsByClassName(className: string): HTMLCollectionOf<Element> {
2507
+ return document.getElementsByClassName(className);
2508
+ }
2509
+ /**
2510
+ * Function to get elements using querySelectorAll
2511
+ */
2512
+ // export function querySelectorAll(args: string, element: Element): ArrayOf<Element> {
2513
+ // return element.querySelectorAll('.' + args);
2514
+ // }
2515
+ /**
2516
+ * Function to get elements using querySelector
2517
+ *
2518
+ * @param {string} args - Specifies the args
2519
+ * @param {string} elementSelector - Specifies the element selector
2520
+ * @returns {Element} - Returns the element
2521
+ */
2522
+ export function querySelector(args: string, elementSelector: string): Element {
2523
+ let targetEle: Element = null;
2524
+ if (document.getElementById(elementSelector)) {
2525
+ targetEle = document.getElementById(elementSelector).querySelector('#' + args);
2526
+ }
2527
+ return targetEle;
2528
+ }
2529
+ /**
2530
+ * Function to get the element for selection and highlight using public method
2531
+ *
2532
+ * @param {number} layerIndex - Specifies the layer index
2533
+ * @param {string} name - Specifies the layer name
2534
+ * @param {boolean} enable - Specifies the boolean value
2535
+ * @param {Maps} map - Specifies the instance of the maps
2536
+ * @returns {Element} - Returns the element
2537
+ */
2538
+ export function getTargetElement(layerIndex: number, name: string, enable: boolean, map: Maps): Element {
2539
+ let shapeIndex: number;
2540
+ let targetId: string;
2541
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2542
+ const shapeData: any[] = <any[]>map.layers[layerIndex].shapeData['features'];
2543
+ for (let i: number = 0; i < shapeData.length; i++) {
2544
+ if (shapeData[i]['properties'].name === name) {
2545
+ targetId = map.element.id + '_' + 'LayerIndex_' + layerIndex + '_shapeIndex_' + i + '_dataIndex_undefined';
2546
+ break;
2547
+ }
2548
+ }
2549
+ const targetEle: Element = getElement(targetId);
2550
+ return targetEle;
2551
+ }
2552
+ /**
2553
+ * Function to create style element for highlight and selection
2554
+ *
2555
+ * @param {string} id - Specifies the id
2556
+ * @param {string} className - Specifies the class name
2557
+ * @param {IShapeSelectedEventArgs | any} eventArgs - Specifies the event args
2558
+ * @returns {Element} - Returns the element
2559
+ */
2560
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2561
+ export function createStyle(id: string, className: string, eventArgs: IShapeSelectedEventArgs | any): Element {
2562
+ return createElement('style', {
2563
+ id: id, innerHTML: '.' + className + '{fill:'
2564
+ + eventArgs['fill'] + ';' + 'fill-opacity:' + (eventArgs['opacity']).toString() + ';' +
2565
+ 'stroke-opacity:' + (eventArgs['border']['opacity']).toString() + ';' +
2566
+ 'stroke-width:' + (eventArgs['border']['width']).toString() + ';' +
2567
+ 'stroke:' + eventArgs['border']['color'] + ';' + '}'
2568
+ });
2569
+ }
2570
+ /**
2571
+ * Function to customize the style for highlight and selection
2572
+ *
2573
+ * @param {string} id - Specifies the id
2574
+ * @param {string} className - Specifies the class name
2575
+ * @param {IShapeSelectedEventArgs | any} eventArgs - Specifies the event args
2576
+ * @returns {void}
2577
+ */
2578
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2579
+ export function customizeStyle(id: string, className: string, eventArgs: IShapeSelectedEventArgs | any): void {
2580
+ const styleEle: Element = getElement(id);
2581
+ if (!isNullOrUndefined(styleEle)) {
2582
+ styleEle.innerHTML = '.' + className + '{fill:'
2583
+ + eventArgs['fill'] + ';' + 'fill-opacity:' + (eventArgs['opacity']).toString() + ';' +
2584
+ 'stroke-width:' + (eventArgs['border']['width']).toString() + ';' +
2585
+ 'stroke-opacity:' + (eventArgs['border']['opacity']).toString() + ';' +
2586
+ 'stroke:' + eventArgs['border']['color'] + '}';
2587
+ }
2588
+ }
2589
+
2590
+ /**
2591
+ * Function to trigger itemSelection event for legend selection and public method
2592
+ *
2593
+ * @param {SelectionSettingsModel} selectionSettings - Specifies the selection settings
2594
+ * @param {Maps} map - Specifies the instance of the maps
2595
+ * @param {Element} targetElement - Specifies the target element
2596
+ * @param {any} shapeData - Specifies the shape data
2597
+ * @param {any} data - Specifies the data
2598
+ * @returns {void}
2599
+ */
2600
+ export function triggerItemSelectionEvent(selectionSettings: SelectionSettingsModel, map: Maps, targetElement: Element,
2601
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2602
+ shapeData: any, data: any): void {
2603
+ const border: BorderModel = {
2604
+ color: selectionSettings.border.color,
2605
+ width: selectionSettings.border.width / map.scale,
2606
+ opacity: selectionSettings.border.opacity
2607
+ };
2608
+ const eventArgs: ISelectionEventArgs = {
2609
+ opacity: selectionSettings.opacity,
2610
+ fill: selectionSettings.fill,
2611
+ border: border,
2612
+ name: itemSelection,
2613
+ target: targetElement.id,
2614
+ cancel: false,
2615
+ shapeData: shapeData,
2616
+ data: data,
2617
+ maps: map
2618
+ };
2619
+ map.trigger('itemSelection', eventArgs, (observedArgs: ISelectionEventArgs) => {
2620
+ eventArgs.border.opacity = isNullOrUndefined(selectionSettings.border.opacity) ? selectionSettings.opacity : selectionSettings.border.opacity;
2621
+ map.shapeSelectionItem.push(eventArgs.shapeData);
2622
+ if (!getElement('ShapeselectionMap')) {
2623
+ document.body.appendChild(createStyle('ShapeselectionMap',
2624
+ 'ShapeselectionMapStyle', eventArgs));
2625
+ } else {
2626
+ customizeStyle('ShapeselectionMap', 'ShapeselectionMapStyle', eventArgs);
2627
+ }
2628
+ });
2629
+ }
2630
+
2631
+ /**
2632
+ * Function to remove class from element
2633
+ *
2634
+ * @param {Element} element - Specifies the element
2635
+ * @returns {void}
2636
+ */
2637
+ export function removeClass(element: Element): void {
2638
+ element.removeAttribute('class');
2639
+ }
2640
+ /**
2641
+ * Animation Effect Calculation End
2642
+ *
2643
+ * @param {Element} element - Specifies the element
2644
+ * @param {number} delay - Specifies the delay
2645
+ * @param {number} duration - Specifies the duration
2646
+ * @param {MapLocation} point - Specifies the location
2647
+ * @param {Maps} maps - Specifies the instance of the maps
2648
+ * @param {string} ele - Specifies the element
2649
+ * @param {number} radius - Specifies the radius
2650
+ * @returns {void}
2651
+ * @private
2652
+ */
2653
+ export function elementAnimate(
2654
+ element: Element, delay: number, duration: number, point: MapLocation, maps: Maps,
2655
+ ele?: string, radius: number = 0
2656
+ ): void {
2657
+ const centerX: number = point.x;
2658
+ const centerY: number = point.y;
2659
+ let height: number = 0;
2660
+ const transform: string = element.getAttribute('transform') || '';
2661
+ new Animation({}).animate(<HTMLElement>element, {
2662
+ duration: duration,
2663
+ delay: delay,
2664
+ progress: (args: AnimationOptions): void => {
2665
+ if (args.timeStamp > args.delay) {
2666
+ if (maps.isTileMap && height === 0) {
2667
+ const layerGroupElement: HTMLElement = document.querySelector('.GroupElement') as HTMLElement;
2668
+ if (!isNullOrUndefined(layerGroupElement)) {
2669
+ layerGroupElement.style.display = 'block';
2670
+ }
2671
+ }
2672
+ height = ((args.timeStamp - args.delay) / args.duration);
2673
+ element.setAttribute('transform', 'translate( ' + (centerX - (radius * height)) + ' ' + (centerY - (radius * height)) +
2674
+ ' ) scale(' + height + ')');
2675
+ }
2676
+ },
2677
+ end: (model: AnimationOptions) => {
2678
+
2679
+ element.setAttribute('transform', transform);
2680
+ if (!ele) {
2681
+ return;
2682
+ }
2683
+ const event: IAnimationCompleteEventArgs = {
2684
+ cancel: false, name: animationComplete, element: ele, maps: maps
2685
+ };
2686
+ maps.trigger(animationComplete, event);
2687
+ }
2688
+ });
2689
+ }
2690
+
2691
+ /**
2692
+ * @param {string} id - Specifies the id
2693
+ * @returns {void}
2694
+ */
2695
+ export function timeout(id: string): void {
2696
+ removeElement(id);
2697
+ }
2698
+
2699
+ /**
2700
+ * @param {string} text - Specifies the text
2701
+ * @param {string} size - Specifies the size
2702
+ * @param {number} x - Specifies the x value
2703
+ * @param {number} y - Specifies the y value
2704
+ * @param {number} areaWidth - Specifies the area width
2705
+ * @param {number} areaHeight - Specifies the area height
2706
+ * @param {string} id - Specifies the id
2707
+ * @param {Element} element - Specifies the element
2708
+ * @param {boolean} isTouch - Specifies the boolean value
2709
+ * @returns {void}
2710
+ */
2711
+ export function showTooltip(
2712
+ text: string, size: string, x: number, y: number, areaWidth: number, areaHeight: number, id: string, element: Element,
2713
+ isTouch?: boolean
2714
+ ): void {
2715
+ const location: MapLocation = getMousePosition(x, y, element);
2716
+ if (!isNullOrUndefined(location)) {
2717
+ x = location.x;
2718
+ y = location.y;
2719
+ }
2720
+ let tooltip: HTMLElement = document.getElementById(id);
2721
+ let width: number = measureText(text, {
2722
+ fontFamily: 'Segoe UI', size: '8px',
2723
+ fontStyle: 'Normal', fontWeight: 'Regular'
2724
+ }).width;
2725
+ const str: string[] = text.split(' ');
2726
+ let demo: number = str[0].length;
2727
+ for (let i: number = 1; i < str.length; i++) {
2728
+ if (demo < str[i].length) {
2729
+ demo = str[i].length;
2730
+ }
2731
+ }
2732
+ if (!tooltip) {
2733
+ tooltip = createElement('div', {
2734
+ id: id,
2735
+ styles: 'background-color: rgb(255, 255, 255) !important; color:black !important; ' +
2736
+ 'position:absolute;border:1px solid rgb(0, 0, 0); padding-left:5px;' +
2737
+ 'font-size:12px; font-family: "Segoe UI"; text-align:center'
2738
+ });
2739
+ }
2740
+ if (x < (areaWidth - width)) {
2741
+ // eslint-disable-next-line no-self-assign
2742
+ x = x;
2743
+ } else if (x > (areaWidth - width) && x < areaWidth - (demo * 8)) {
2744
+ width = (areaWidth - x);
2745
+ } else if (x >= areaWidth - demo * 8) {
2746
+ if (x > width) {
2747
+ x = x - width;
2748
+ } else {
2749
+ width = x;
2750
+ x = 0;
2751
+ }
2752
+ }
2753
+ const size1: string[] = size.split('px');
2754
+ wordWrap(tooltip, text, x, y, size1, width, areaWidth, element);
2755
+ const height: number = tooltip.clientHeight;
2756
+ if ((height + parseInt(size1[0], 10) * 2) > areaHeight) {
2757
+ width = x;
2758
+ x = 0;
2759
+ }
2760
+ wordWrap(tooltip, text, x, y, size1, width, areaWidth, element);
2761
+ if (isTouch) {
2762
+ setTimeout(timeout, 5000, id);
2763
+ }
2764
+ }
2765
+
2766
+ /**
2767
+ * @param {HTMLElement} tooltip - Specifies the tooltip element
2768
+ * @param {string} text - Specifies the text
2769
+ * @param {number} x - Specifies the x value
2770
+ * @param {number} y - Specifies the y value
2771
+ * @param {string[]} size1 - Specifies the size
2772
+ * @param {number} width - Specifies the width
2773
+ * @param {number} areaWidth - Specifies the area width
2774
+ * @param {Element} element - Specifies the element
2775
+ * @returns {void}
2776
+ */
2777
+ export function wordWrap(
2778
+ tooltip: HTMLElement, text: string, x: number, y: number, size1: string[], width: number,
2779
+ areaWidth: number, element: Element
2780
+ ): void {
2781
+ tooltip.innerHTML = text;
2782
+ tooltip.style.top = tooltip.id.indexOf('_Legend') !== -1 ?
2783
+ (parseInt(size1[0], 10) + y).toString() + 'px' : (parseInt(size1[0], 10) * 2).toString() + 'px';
2784
+ tooltip.style.left = (x).toString() + 'px';
2785
+ tooltip.style.width = width.toString() + 'px';
2786
+ tooltip.style.maxWidth = (areaWidth).toString() + 'px';
2787
+ tooltip.style.wordWrap = 'break-word';
2788
+ element.appendChild(tooltip);
2789
+ }
2790
+ // /**
2791
+ // *
2792
+ // * @param touchList
2793
+ // * @param e
2794
+ // * @param touches
2795
+ // */
2796
+ // export function addTouchPointer(touchList: ITouches[], e: PointerEvent, touches: TouchList): ITouches[] {
2797
+ // if (touches) {
2798
+ // touchList = [];
2799
+ // for (let i: number = 0, length: number = touches.length; i < length; i++) {
2800
+ // touchList.push({ pageX: touches[i].clientX, pageY: touches[i].clientY, pointerId: null });
2801
+ // }
2802
+ // } else {
2803
+ // touchList = touchList ? touchList : [];
2804
+ // if (touchList.length === 0) {
2805
+ // touchList.push({ pageX: e.clientX, pageY: e.clientY, pointerId: e.pointerId });
2806
+ // } else {
2807
+ // for (let i: number = 0, length: number = touchList.length; i < length; i++) {
2808
+ // if (touchList[i].pointerId === e.pointerId) {
2809
+ // touchList[i] = { pageX: e.clientX, pageY: e.clientY, pointerId: e.pointerId };
2810
+ // } else {
2811
+ // touchList.push({ pageX: e.clientX, pageY: e.clientY, pointerId: e.pointerId });
2812
+ // }
2813
+ // }
2814
+ // }
2815
+ // }
2816
+ // return touchList;
2817
+ // }
2818
+
2819
+ /**
2820
+ * @param {string} id - Specifies the id
2821
+ * @param {string} text - Specifies the text
2822
+ * @param {string} top - Specifies the top
2823
+ * @param {string} left - Specifies the left
2824
+ * @param {string} fontSize - Specifies the fontSize
2825
+ * @returns {void}
2826
+ * @private
2827
+ */
2828
+ export function createTooltip(id: string, text: string, top: number, left: number, fontSize: string): void {
2829
+ let tooltip: HTMLElement = getElement(id) as HTMLElement;
2830
+ const style: string = 'top:' + top.toString() + 'px;' +
2831
+ 'left:' + left.toString() + 'px;' +
2832
+ 'color: #000000; ' +
2833
+ 'background:' + '#FFFFFF' + ';' +
2834
+ 'z-index: 2;' +
2835
+ 'position:absolute;border:1px solid #707070;font-size:' + fontSize + ';border-radius:2px;';
2836
+ if (!tooltip) {
2837
+ tooltip = createElement('div', {
2838
+ id: id, innerHTML: '&nbsp;' + text + '&nbsp;', styles: style
2839
+ });
2840
+ document.body.appendChild(tooltip);
2841
+ } else {
2842
+ tooltip.setAttribute('innerHTML', '&nbsp;' + text + '&nbsp;');
2843
+ tooltip.setAttribute('styles', style);
2844
+ }
2845
+ }
2846
+
2847
+ /**
2848
+ * @param {Point} location - Specifies the location
2849
+ * @param {string} shape - Specifies the shape
2850
+ * @param {Size} size - Specifies the size
2851
+ * @param {string} url - Specifies the url
2852
+ * @param {PathOption} options - Specifies the options
2853
+ * @returns {Element} - Returns the element
2854
+ * @private
2855
+ */
2856
+ export function drawSymbol(location: Point, shape: string, size: Size, url: string, options: PathOption): Element {
2857
+ const functionName: string = 'Path';
2858
+ const renderer: SvgRenderer = new SvgRenderer('');
2859
+ const temp: IShapes = renderLegendShape(location, size, shape, options, url);
2860
+ const htmlObject: Element = renderer['draw' + temp.functionName](temp.renderOption);
2861
+ return htmlObject;
2862
+ }
2863
+
2864
+
2865
+ /**
2866
+ * @param {MapLocation} location - Specifies the location
2867
+ * @param {Size} size - Specifies the size
2868
+ * @param {string} shape - Specifies the shape
2869
+ * @param {PathOption} options - Specifies the path options
2870
+ * @param {string} url - Specifies the url
2871
+ * @returns {IShapes} - Returns the shapes
2872
+ * @private
2873
+ */
2874
+ export function renderLegendShape(location: MapLocation, size: Size, shape: string, options: PathOption, url: string): IShapes {
2875
+ let renderPath: string;
2876
+ let functionName: string = 'Path';
2877
+ const shapeWidth: number = size.width;
2878
+ const shapeHeight: number = size.height;
2879
+ const shapeX: number = location.x;
2880
+ const shapeY: number = location.y;
2881
+ const x: number = location.x + (-shapeWidth / 2);
2882
+ const y: number = location.y + (-shapeHeight / 2);
2883
+ options['stroke'] = (shape === 'HorizontalLine' || shape === 'VerticalLine' || shape === 'Cross') ? options['fill'] : options['stroke'];
2884
+ options['stroke-width'] = (options['stroke-width'] === 0 && (shape === 'HorizontalLine' || shape === 'VerticalLine' || shape === 'Cross')) ? 1: options['stroke-width'];
2885
+ switch (shape) {
2886
+ case 'Circle':
2887
+ case 'Bubble':
2888
+ functionName = 'Ellipse';
2889
+ merge(options, { 'rx': shapeWidth / 2, 'ry': shapeHeight / 2, 'cx': shapeX, 'cy': shapeY });
2890
+ break;
2891
+ case 'VerticalLine':
2892
+ renderPath = 'M' + ' ' + shapeX + ' ' + (shapeY + (shapeHeight / 2)) + ' ' + 'L' + ' ' + shapeX + ' '
2893
+ + (shapeY + (-shapeHeight / 2));
2894
+ merge(options, { 'd': renderPath });
2895
+ break;
2896
+ case 'HorizontalLine':
2897
+ renderPath = 'M' + ' ' + shapeX + ' ' + shapeY + ' ' + 'L' + ' ' + (shapeX + (shapeWidth / 2)) + ' '
2898
+ + shapeY;
2899
+ merge(options, { 'd': renderPath });
2900
+ break;
2901
+ case 'Diamond':
2902
+ renderPath = 'M' + ' ' + x + ' ' + shapeY + ' ' +
2903
+ 'L' + ' ' + shapeX + ' ' + (shapeY + (-shapeHeight / 2)) + ' ' +
2904
+ 'L' + ' ' + (shapeX + (shapeWidth / 2)) + ' ' + shapeY + ' ' +
2905
+ 'L' + ' ' + shapeX + ' ' + (shapeY + (shapeHeight / 2)) + ' ' +
2906
+ 'L' + ' ' + x + ' ' + shapeY + ' z';
2907
+ merge(options, { 'd': renderPath });
2908
+ break;
2909
+ case 'Rectangle':
2910
+ renderPath = 'M' + ' ' + x + ' ' + (shapeY + (-shapeHeight / 2)) + ' ' +
2911
+ 'L' + ' ' + (shapeX + (shapeWidth / 2)) + ' ' + (shapeY + (-shapeHeight / 2)) + ' ' +
2912
+ 'L' + ' ' + (shapeX + (shapeWidth / 2)) + ' ' + (shapeY + (shapeHeight / 2)) + ' ' +
2913
+ 'L' + ' ' + x + ' ' + (shapeY + (shapeHeight / 2)) + ' ' +
2914
+ 'L' + ' ' + x + ' ' + (shapeY + (-shapeHeight / 2)) + ' z';
2915
+ merge(options, { 'd': renderPath });
2916
+ break;
2917
+ case 'Triangle':
2918
+ renderPath = 'M' + ' ' + x + ' ' + (shapeY + (shapeHeight / 2)) + ' ' +
2919
+ 'L' + ' ' + shapeX + ' ' + (shapeY + (-shapeHeight / 2)) + ' ' +
2920
+ 'L' + ' ' + (shapeX + (shapeWidth / 2)) + ' ' + (shapeY + (shapeHeight / 2)) + ' ' +
2921
+ 'L' + ' ' + x + ' ' + (shapeY + (shapeHeight / 2)) + ' z';
2922
+ merge(options, { 'd': renderPath });
2923
+ break;
2924
+ case 'InvertedTriangle':
2925
+ renderPath = 'M' + ' ' + (shapeX + (shapeWidth / 2)) + ' ' + (shapeY - (shapeHeight / 2)) + ' ' +
2926
+ 'L' + ' ' + shapeX + ' ' + (shapeY + (shapeHeight / 2)) + ' ' +
2927
+ 'L' + ' ' + (shapeX - (shapeWidth / 2)) + ' ' + (shapeY - (shapeHeight / 2)) + ' ' +
2928
+ 'L' + ' ' + (shapeX + (shapeWidth / 2)) + ' ' + (shapeY - (shapeHeight / 2)) + ' z';
2929
+ merge(options, { 'd': renderPath });
2930
+ break;
2931
+ case 'Pentagon':
2932
+ // eslint-disable-next-line no-case-declarations
2933
+ const eq: number = 72; let xValue: number; let yValue: number;
2934
+ for (let i: number = 0; i <= 5; i++) {
2935
+ xValue = (shapeWidth / 2) * Math.cos((Math.PI / 180) * (i * eq));
2936
+ yValue = (shapeWidth / 2) * Math.sin((Math.PI / 180) * (i * eq));
2937
+ if (i === 0) {
2938
+ renderPath = 'M' + ' ' + (shapeX + xValue) + ' ' + (shapeY + yValue) + ' ';
2939
+ } else {
2940
+ renderPath = renderPath.concat('L' + ' ' + (shapeX + xValue) + ' ' + (shapeY + yValue) + ' ');
2941
+ }
2942
+ }
2943
+ renderPath = renderPath.concat('Z');
2944
+ merge(options, { 'd': renderPath });
2945
+ break;
2946
+ case 'Star':
2947
+ renderPath = 'M ' + (location.x + size.width / 3) + ' ' + (location.y - size.height / 2) + ' L ' + (location.x - size.width / 2)
2948
+ + ' ' + (location.y + size.height / 6) + ' L ' + (location.x + size.width / 2) + ' ' + (location.y + size.height / 6)
2949
+ + ' L ' + (location.x - size.width / 3) + ' ' + (location.y - size.height / 2) + ' L ' + location.x + ' ' +
2950
+ (location.y + size.height / 2) + ' L ' + (location.x + size.width / 3) + ' ' + (location.y - size.height / 2) + ' Z';
2951
+ merge(options, { 'd': renderPath });
2952
+ break;
2953
+ case 'Cross':
2954
+ renderPath = 'M' + ' ' + x + ' ' + shapeY + ' ' + 'L' + ' ' + (shapeX + (shapeWidth / 2)) + ' ' + shapeY + ' ' +
2955
+ 'M' + ' ' + shapeX + ' ' + (shapeY + (shapeHeight / 2)) + ' ' + 'L' + ' ' + shapeX + ' ' +
2956
+ (shapeY + (-shapeHeight / 2));
2957
+ merge(options, { 'd': renderPath });
2958
+ break;
2959
+ case 'Image':
2960
+ functionName = 'Image';
2961
+ merge(options, { 'href': url, 'height': shapeHeight, 'width': shapeWidth, x: x, y: y });
2962
+ break;
2963
+ }
2964
+ return { renderOption: options, functionName: functionName };
2965
+ }
2966
+ /**
2967
+ * Animation Effect Calculation End
2968
+ *
2969
+ * @private
2970
+ */
2971
+
2972
+ // export function markerTemplateAnimate(element: Element, delay: number, duration: number, point: MapLocation): void {
2973
+ // let delta: number = 0;
2974
+ // let top: string = (element as HTMLElement).style.top;
2975
+ // let y: number = parseInt(top, 10);
2976
+ // new Animation({}).animate(<HTMLElement>element, {
2977
+ // duration: duration,
2978
+ // delay: delay,
2979
+ // progress: (args: AnimationOptions): void => {
2980
+ // if (args.timeStamp > args.delay) {
2981
+ // delta = ((args.timeStamp - args.delay) / args.duration);
2982
+ // (element as HTMLElement).style.top = y - 100 + (delta * 100) + 'px';
2983
+ // }
2984
+ // },
2985
+ // end: (model: AnimationOptions) => {
2986
+ // (element as HTMLElement).style.top = top;
2987
+ // }
2988
+ // });
2989
+ // }
2990
+
2991
+ /**
2992
+ * @param {HTMLElement} childElement - Specifies the child element
2993
+ * @param {HTMLElement} parentElement - Specifies the parent element
2994
+ * @returns {Size} - Returns the size
2995
+ * @private
2996
+ */
2997
+ export function getElementOffset(childElement: HTMLElement, parentElement: HTMLElement): Size {
2998
+ parentElement.appendChild(childElement);
2999
+ const width: number = childElement.offsetWidth;
3000
+ const height: number = childElement.offsetHeight;
3001
+ parentElement.removeChild(childElement);
3002
+ return new Size(width, height);
3003
+ }
3004
+
3005
+ /**
3006
+ * @param {Element} element - Specifies the element
3007
+ * @param {number} index - Specifies the element
3008
+ * @param {number} scale - Specifies the scale
3009
+ * @param {Maps} maps - Specifies the instance of the maps
3010
+ * @returns {void}
3011
+ * @private
3012
+ */
3013
+ export function changeBorderWidth(element: Element, index: number, scale: number, maps: Maps): void {
3014
+ let childNode: HTMLElement;
3015
+ for (let l: number = 0; l < element.childElementCount; l++) {
3016
+ childNode = element.childNodes[l] as HTMLElement;
3017
+ if (childNode.id.indexOf('_NavigationGroup') > -1) {
3018
+ changeNavaigationLineWidth(childNode, index, scale, maps);
3019
+ } else {
3020
+ let currentStroke: number;
3021
+ let value: number = 0;
3022
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3023
+ const borderWidthValue: any = maps.layersCollection[index].shapeSettings.borderWidthValuePath;
3024
+ const borderWidth: number = (<LayerSettingsModel>maps.layersCollection[index]).shapeSettings.border.width;
3025
+ const circleRadius: number = (<LayerSettingsModel>maps.layersCollection[index]).shapeSettings.circleRadius;
3026
+ if (maps.layersCollection[index].shapeSettings.borderWidthValuePath) {
3027
+ value = checkShapeDataFields(
3028
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3029
+ <any[]>maps.layersCollection[index].dataSource, maps.layersCollection[index].layerData[l]['property'],
3030
+ maps.layersCollection[index].shapeDataPath, maps.layersCollection[index].shapePropertyPath, maps.layersCollection[index]
3031
+ );
3032
+ if (value !== null) {
3033
+ if (maps.layersCollection[index].dataSource[value][borderWidthValue]) {
3034
+ currentStroke = maps.layersCollection[index].dataSource[value][borderWidthValue];
3035
+ } else {
3036
+ currentStroke = (isNullOrUndefined(borderWidth) ? 0 : borderWidth);
3037
+ }
3038
+ } else {
3039
+ currentStroke = (isNullOrUndefined(borderWidth) ? 0 : borderWidth);
3040
+ }
3041
+ } else {
3042
+ currentStroke = (isNullOrUndefined(borderWidth) ? 0 : borderWidth);
3043
+ }
3044
+ childNode.setAttribute('stroke-width', (currentStroke / scale).toString());
3045
+ if (element.id.indexOf('_Point') > -1 || element.id.indexOf('_MultiPoint') > -1) {
3046
+ childNode.setAttribute('r', (circleRadius / scale).toString());
3047
+ }
3048
+ }
3049
+ }
3050
+ }
3051
+
3052
+ /**
3053
+ * @param {Element} element - Specifies the element
3054
+ * @param {number} index - Specifies the element
3055
+ * @param {number} scale - Specifies the scale
3056
+ * @param {Maps} maps - Specifies the instance of the maps
3057
+ * @returns {void}
3058
+ * @private
3059
+ */
3060
+ export function changeNavaigationLineWidth(element: Element, index: number, scale: number, maps: Maps): void {
3061
+ let node: HTMLElement;
3062
+ for (let m: number = 0; m < element.childElementCount; m++) {
3063
+ node = element.childNodes[m] as HTMLElement;
3064
+ if (node.tagName === 'path') {
3065
+ const currentStroke: number = ((<LayerSettingsModel>maps.layersCollection[index])
3066
+ .navigationLineSettings[parseFloat(node.id.split('_NavigationIndex_')[1].split('_')[0])].width);
3067
+ node.setAttribute('stroke-width', (currentStroke / scale).toString());
3068
+ }
3069
+ }
3070
+ }
3071
+
3072
+ // /** Pinch zoom helper methods */
3073
+
3074
+ /**
3075
+ * @param {PointerEvent | TouchEvent} event - Specifies the pointer or touch event
3076
+ * @returns {ITouches[]} - Returns the target
3077
+ * @private */
3078
+ export function targetTouches(event: PointerEvent | TouchEvent): ITouches[] {
3079
+ const targetTouches: ITouches[] = [];
3080
+ const touches: TouchList = (<TouchEvent & PointerEvent>event).touches;
3081
+ for (let i: number = 0; i < touches.length; i++) {
3082
+ targetTouches.push({ pageX: touches[i].pageX, pageY: touches[i].pageY });
3083
+ }
3084
+ return targetTouches;
3085
+ }
3086
+
3087
+ /**
3088
+ * @param {ITouches[]} startTouches - Specifies the start touches
3089
+ * @param {ITouches[]} endTouches - Specifies the end touches
3090
+ * @returns {number} - Returns the number
3091
+ * @private
3092
+ */
3093
+ export function calculateScale(startTouches: ITouches[], endTouches: ITouches[]): number {
3094
+ const startDistance: number = getDistance(startTouches[0], startTouches[1]);
3095
+ const endDistance: number = getDistance(endTouches[0], endTouches[1]);
3096
+ return (endDistance / startDistance);
3097
+ }
3098
+
3099
+ /**
3100
+ * @param {ITouches} a - Specifies the a value
3101
+ * @param {ITouches} b - Specifies the b value
3102
+ * @returns {number} - Returns the number
3103
+ * @private */
3104
+ export function getDistance(a: ITouches, b: ITouches): number {
3105
+ const x: number = a.pageX - b.pageX;
3106
+ const y: number = a.pageY - b.pageY;
3107
+ return Math.sqrt(x * x + y * y);
3108
+ }
3109
+
3110
+ /**
3111
+ * @param {ITouches[]} touches - Specifies the touches
3112
+ * @param {Maps} maps - Specifies the instance of the maps
3113
+ * @returns {any[]} - Returns the object
3114
+ * @private
3115
+ */
3116
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3117
+ export function getTouches(touches: ITouches[], maps: Maps): any[] {
3118
+ const rect: ClientRect = maps.element.getBoundingClientRect();
3119
+ const posTop: number = rect.top + document.defaultView.pageXOffset;
3120
+ const posLeft: number = rect.left + document.defaultView.pageYOffset;
3121
+ return Array.prototype.slice.call(touches).map((touch: ITouches) => {
3122
+ return {
3123
+ x: touch.pageX - posLeft,
3124
+ y: touch.pageY - posTop
3125
+ };
3126
+ });
3127
+ }
3128
+
3129
+ /**
3130
+ * @param {any[]} touches - Specifies the touches
3131
+ * @returns {Point} - Returns the point
3132
+ * @private
3133
+ */
3134
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3135
+ export function getTouchCenter(touches: any[]): Point {
3136
+ return {
3137
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3138
+ x: touches.map((e: any) => { return e['x']; }).reduce(sum) / touches.length,
3139
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3140
+ y: touches.map((e: any) => { return e['y']; }).reduce(sum) / touches.length
3141
+ };
3142
+ }
3143
+
3144
+ /**
3145
+ * @param {number} a - Specifies a value
3146
+ * @param {number} b - Specifies b value
3147
+ * @returns {number} - Returns the sum of a and b
3148
+ * @private
3149
+ */
3150
+ export function sum(a: number, b: number): number {
3151
+ return a + b;
3152
+ }
3153
+
3154
+ /**
3155
+ * Animation Effect Calculation End
3156
+ *
3157
+ * @param {Element} element - Specifies the element.
3158
+ * @param {number} delay - Specifies the delay.
3159
+ * @param {number} duration - Specifies the duration.
3160
+ * @param {MapLocation} point - Specifies the location.
3161
+ * @param {number} scale - Specifies the scale value.
3162
+ * @param {Size} size - Specifies the size.
3163
+ * @param {Maps} maps - Specifies the maps.
3164
+ * @returns {void}
3165
+ * @private
3166
+ */
3167
+ export function zoomAnimate(
3168
+ element: Element, delay: number, duration: number, point: MapLocation, scale: number, size: Size,
3169
+ maps: Maps
3170
+ ): void {
3171
+ let delta: number = 0;
3172
+ const previousLocation: MapLocation = maps.previousPoint;
3173
+ const preScale: number = maps.previousScale;
3174
+ const diffScale: number = scale - preScale;
3175
+ const currentLocation: MapLocation = new MapLocation(0, 0);
3176
+ let currentScale: number = 1;
3177
+ if (scale === preScale) {
3178
+ element.setAttribute('transform', 'scale( ' + (scale) + ' ) translate( ' + point.x + ' ' + point.y + ' )');
3179
+ return;
3180
+ }
3181
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3182
+ const slope: any = (previousLocation: MapLocation, point: MapLocation): number => {
3183
+ if (previousLocation.x === point.x) {
3184
+ return null;
3185
+ }
3186
+ return (point.y - previousLocation.y) / (point.x - previousLocation.x);
3187
+ };
3188
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3189
+ const intercept: any = (point: MapLocation, slopeValue: number): number => {
3190
+ if (slopeValue === null) {
3191
+ return point.x;
3192
+ }
3193
+ return point.y - slopeValue * point.x;
3194
+ };
3195
+ const slopeFactor: number = slope(previousLocation, point);
3196
+ const slopeIntersection: number = intercept(previousLocation, slopeFactor);
3197
+ const horizontalDifference: number = point.x - previousLocation.x;
3198
+ const verticalDifference: number = point.y - previousLocation.y;
3199
+ animate(
3200
+ <HTMLElement>element, delay, duration,
3201
+ (args: AnimationOptions): void => {
3202
+ if (args.timeStamp > args.delay) {
3203
+ delta = ((args.timeStamp - args.delay) / args.duration);
3204
+ currentScale = preScale + (delta * diffScale);
3205
+ currentLocation.x = previousLocation.x + (delta * horizontalDifference) / (currentScale / scale);
3206
+ if (slopeFactor == null) {
3207
+ currentLocation.y = previousLocation.y + (delta * verticalDifference);
3208
+ } else {
3209
+ currentLocation.y = ((slopeFactor * currentLocation.x) + slopeIntersection);
3210
+ }
3211
+ args.element.setAttribute('transform', 'scale( ' + currentScale + ' ) ' +
3212
+ 'translate( ' + currentLocation.x + ' ' + currentLocation.y + ' )');
3213
+ maps.translatePoint = currentLocation;
3214
+ maps.scale = currentScale;
3215
+ maps.zoomModule.processTemplate(point.x, point.y, currentScale, maps);
3216
+ }
3217
+ },
3218
+ () => {
3219
+ maps.translatePoint = point;
3220
+ maps.scale = scale;
3221
+ element.setAttribute('transform', 'scale( ' + (scale) + ' ) translate( ' + point.x + ' ' + point.y + ' )');
3222
+ maps.zoomModule.processTemplate(point.x, point.y, scale, maps);
3223
+ }
3224
+ );
3225
+ }
3226
+ /**
3227
+ * To process custom animation
3228
+ *
3229
+ * @param {Element} element - Specifies the element
3230
+ * @param {number} delay - Specifies the delay
3231
+ * @param {number} duration - Specifies the duration
3232
+ * @param {Function} process - Specifies the process
3233
+ * @param {Function} end - Specifies the end
3234
+ * @returns {void}
3235
+ */
3236
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3237
+ export function animate(element: Element, delay: number, duration: number, process: any, end: any): void {
3238
+ let start: number = null;
3239
+ // eslint-disable-next-line prefer-const
3240
+ let clearAnimation: number;
3241
+ const markerStyle: string = 'visibility:visible';
3242
+ const startAnimation: FrameRequestCallback = (timestamp: number) => {
3243
+ if (!start) { start = timestamp; }
3244
+ const progress: number = timestamp - start;
3245
+ if (progress < duration) {
3246
+ process.call(this, { element: element, delay: 0, timeStamp: progress, duration: duration });
3247
+ window.requestAnimationFrame(startAnimation);
3248
+ } else {
3249
+ window.cancelAnimationFrame(clearAnimation);
3250
+ end.call(this, { element: element });
3251
+ if (element.id.indexOf('Marker') > -1) {
3252
+ let markerElement: Element = getElementByID(element.id.split('_Layer')[0] + '_Markers_Group');
3253
+ markerElement.setAttribute('style', markerStyle);
3254
+ }
3255
+ }
3256
+ };
3257
+ clearAnimation = window.requestAnimationFrame(startAnimation);
3258
+ }
3259
+ /**
3260
+ * To get shape data file using Ajax.
3261
+ */
3262
+ export class MapAjax {
3263
+ /**
3264
+ * MapAjax data options
3265
+ */
3266
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3267
+ public dataOptions: string | any;
3268
+ /**
3269
+ * MapAjax type value
3270
+ */
3271
+ public type: string;
3272
+ /**
3273
+ * MapAjax async value
3274
+ */
3275
+ public async: boolean;
3276
+ /**
3277
+ * MapAjax contentType value
3278
+ */
3279
+ public contentType: string;
3280
+ /**
3281
+ * MapAjax sendData value
3282
+ */
3283
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3284
+ public sendData: string | any;
3285
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3286
+ constructor(options: string | any, type?: string, async?: boolean, contentType?: string, sendData?: string | any) {
3287
+ this.dataOptions = options;
3288
+ this.type = type || 'GET';
3289
+ this.async = async || true;
3290
+ this.contentType = contentType;
3291
+ this.sendData = sendData;
3292
+ }
3293
+ }
3294
+
3295
+ /**
3296
+ * Animation Translate
3297
+ *
3298
+ * @param {Element} element - Specifies the element
3299
+ * @param {number} delay - Specifies the delay
3300
+ * @param {number} duration - Specifies the duration
3301
+ * @param {MapLocation} point - Specifies the location
3302
+ * @returns {void}
3303
+ * @private
3304
+ */
3305
+ export function smoothTranslate(element: Element, delay: number, duration: number, point: MapLocation): void {
3306
+ let delta: number = 0;
3307
+ const transform: string[] = element.getAttribute('transform').split(' ');
3308
+ if (transform.length === 2) { transform[2] = transform[1].split(')')[0]; transform[1] = transform[0].split('(')[1]; }
3309
+ const previousLocation: MapLocation = new MapLocation(parseInt(transform[1], 10), parseInt(transform[2], 10));
3310
+ const diffx: number = point.x - previousLocation.x;
3311
+ const diffy: number = point.y - previousLocation.y;
3312
+ const currentLocation: MapLocation = new MapLocation(0, 0);
3313
+ animate(
3314
+ <HTMLElement>element, delay, duration, (args: AnimationOptions): void => {
3315
+ if (args.timeStamp > args.delay) {
3316
+ delta = ((args.timeStamp - args.delay) / args.duration);
3317
+ currentLocation.x = previousLocation.x + (delta * diffx);
3318
+ currentLocation.y = previousLocation.y + (delta * diffy);
3319
+ args.element.setAttribute('transform', 'translate( ' + currentLocation.x + ' ' + currentLocation.y + ' )');
3320
+ }
3321
+ },
3322
+ () => {
3323
+ element.setAttribute('transform', 'translate( ' + point.x + ' ' + point.y + ' )');
3324
+ }
3325
+ );
3326
+ }
3327
+ /**
3328
+ * To find compare should zoom factor with previous factor and current factor
3329
+ *
3330
+ * @param {number} scaleFactor - Specifies the scale factor
3331
+ * @param {Maps} maps - Specifies the instance of the maps
3332
+ * @returns {void}
3333
+ */
3334
+ export function compareZoomFactor(scaleFactor: number, maps: Maps): void {
3335
+ const previous: number = isNullOrUndefined(maps.shouldZoomPreviousFactor) ?
3336
+ null : maps.shouldZoomPreviousFactor;
3337
+ const current: number = isNullOrUndefined(maps.shouldZoomCurrentFactor) ?
3338
+ null : maps.shouldZoomCurrentFactor;
3339
+ if (!isNullOrUndefined(current)) {
3340
+ maps.shouldZoomCurrentFactor = null;
3341
+ maps.shouldZoomPreviousFactor = null;
3342
+ } else if (!isNullOrUndefined(previous)
3343
+ && isNullOrUndefined(current)
3344
+ && maps.shouldZoomPreviousFactor !== scaleFactor) {
3345
+ maps.shouldZoomCurrentFactor = scaleFactor;
3346
+ } else {
3347
+ maps.shouldZoomPreviousFactor = scaleFactor;
3348
+ }
3349
+ }
3350
+ /**
3351
+ * To find zoom level for the min and max latitude values
3352
+ *
3353
+ * @param {number} minLat - Specifies the minimum latitude
3354
+ * @param {number} maxLat - Specifies the maximum latitude
3355
+ * @param {number} minLong - Specifies the minimum longitude
3356
+ * @param {number} maxLong - Specifies the maximum longitude
3357
+ * @param {number} mapWidth - Specifies the width of the maps
3358
+ * @param {number} mapHeight - Specifies the height of the maps
3359
+ * @param {Maps} maps - Specifies the instance of the maps
3360
+ * @returns {number} - Returns the scale factor
3361
+ */
3362
+ export function calculateZoomLevel(minLat: number, maxLat: number, minLong: number, maxLong: number,
3363
+ mapWidth: number, mapHeight: number, maps: Maps): number {
3364
+ let scaleFactor: number;
3365
+ const maxZoomFact: number = maps.zoomSettings.maxZoom;
3366
+ let applyMethodeZoom: number;
3367
+ const maxLatSin: number = Math.sin(maxLat * Math.PI / 180);
3368
+ const maxLatRad: number = Math.log((1 + maxLatSin) / (1 - maxLatSin)) / 2;
3369
+ const maxLatValue: number = Math.max(Math.min(maxLatRad, Math.PI), -Math.PI) / 2;
3370
+ const minLatSin: number = Math.sin(minLat * Math.PI / 180);
3371
+ const minLatRad: number = Math.log((1 + minLatSin) / (1 - minLatSin)) / 2;
3372
+ const minLatValue: number = Math.max(Math.min(minLatRad, Math.PI), -Math.PI) / 2;
3373
+
3374
+ if (maps.zoomNotApplied && !maps.isTileMap) {
3375
+ const latiRatio: number = Math.abs((maps.baseMapBounds.latitude.max - maps.baseMapBounds.latitude.min) / (maxLat - minLat));
3376
+ const longiRatio: number = Math.abs((maps.baseMapBounds.longitude.max - maps.baseMapBounds.longitude.min) / (maxLong - minLong));
3377
+ applyMethodeZoom = Math.min(latiRatio, longiRatio);
3378
+
3379
+
3380
+ const minLocation: Point = convertGeoToPoint(minLat, minLong, 1, maps.layersCollection[0], maps);
3381
+ const maxLocation: Point = convertGeoToPoint(maxLat, maxLong, 1, maps.layersCollection[0], maps);
3382
+ }
3383
+
3384
+ const latRatio: number = (maxLatValue - minLatValue) / Math.PI;
3385
+ const lngDiff: number = maxLong - minLong;
3386
+ const lngRatio: number = ((lngDiff < 0) ? (lngDiff + 360) : lngDiff) / 360;
3387
+ const WORLD_PX_HEIGHT: number = 256;
3388
+ const WORLD_PX_WIDTH: number = 256;
3389
+ const latZoom: number = (Math.log(mapHeight / WORLD_PX_HEIGHT / latRatio) / Math.LN2);
3390
+ const lngZoom: number = (Math.log(mapWidth / WORLD_PX_WIDTH / lngRatio) / Math.LN2);
3391
+ const result: number = (maps.zoomNotApplied && !maps.isTileMap) ? applyMethodeZoom : Math.min(latZoom, lngZoom);
3392
+ scaleFactor = Math.min(result, maxZoomFact);
3393
+ scaleFactor = maps.isTileMap || !maps.zoomNotApplied ? Math.floor(scaleFactor) : scaleFactor;
3394
+ if (!maps.isTileMap) {
3395
+ compareZoomFactor(scaleFactor, maps);
3396
+ }
3397
+ return scaleFactor;
3398
+ }
3399
+
3400
+ /**
3401
+ * Method to get the result
3402
+ *
3403
+ * @param {any} e - Specifies the any type value
3404
+ * @returns {any} - Returns the data value
3405
+ */
3406
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3407
+ export function processResult(e: any): any {
3408
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3409
+ let dataValue: any;
3410
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3411
+ const resultValue: any = !isNullOrUndefined(e['result']) ? e['result'] : e['actual'];
3412
+ if (isNullOrUndefined(resultValue.length)) {
3413
+ if (!isNullOrUndefined(resultValue['Items'])) {
3414
+ dataValue = resultValue['Items'];
3415
+ }
3416
+ }
3417
+ else {
3418
+ dataValue = resultValue;
3419
+ }
3420
+ return dataValue;
3421
+ }