@syncfusion/ej2-maps 30.2.4 → 31.2.2

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