UNPKG

@syncfusion/ej2-maps

Version:

The Maps component is used to visualize the geographical data and represent the statistical data of a particular geographical area on earth with user interactivity, and provides various customizing options

1,181 lines (1,180 loc) 168 kB
var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); /* eslint-disable max-len */ /** * Helper functions for maps control */ import { createElement, isNullOrUndefined, remove, compile as templateComplier, merge, SanitizeHtmlHelper } from '@syncfusion/ej2-base'; import { Animation, animationMode } from '@syncfusion/ej2-base'; import { SvgRenderer } from '@syncfusion/ej2-svg-base'; import { itemSelection } from '../../index'; import { animationComplete } from '../index'; import { markerClusterRendering } from '../index'; /** * Specifies the size information of an element. */ var Size = /** @class */ (function () { function Size(width, height) { this.width = width; this.height = height; } return Size; }()); export { Size }; /** * To find number from string. * * @param {string} value Specifies the value * @param {number} containerSize Specifies the container size * @returns {number} Returns the number * @private */ export function stringToNumber(value, containerSize) { if (typeof value !== 'string') { return value; } if (!isNullOrUndefined(value)) { return value.indexOf('%') !== -1 ? (containerSize / 100) * parseInt(value, 10) : parseInt(value, 10); } return null; } /** * Method to calculate the width and height of the maps. * * @param {Maps} maps Specifies the maps instance * @returns {void} * @private */ export function calculateSize(maps) { maps.element.style.height = !isNullOrUndefined(maps.height) ? maps.height : 'auto'; maps.element.style.width = !isNullOrUndefined(maps.width) ? maps.width : 'auto'; maps.element.style.setProperty('display', 'block'); var containerWidth = maps.element.clientWidth; var containerHeight = maps.element.clientHeight; var containerElementWidth = (typeof maps.element.style.width === 'string') ? stringToNumber(maps.element.style.width, containerWidth) : maps.element.style.width; var containerElementHeight = (typeof maps.element.style.height === 'string') ? stringToNumber(maps.element.style.height, containerHeight) : maps.element.style.height; var availableSize = new Size(0, 0); if (maps.width === '0px' || maps.width === '0%' || maps.height === '0%' || maps.height === '0px') { availableSize = new Size(0, 0); } else { availableSize = new Size(stringToNumber(maps.width, containerWidth) || containerWidth || containerElementWidth || 600, stringToNumber(maps.height, containerHeight) || containerHeight || containerElementHeight || (maps.isDevice ? Math.min(window.innerWidth, window.innerHeight) : 450)); } return availableSize; } /** * Method to create svg for maps. * * @param {Maps} maps Specifies the map instance * @returns {void} * @private */ export function createSvg(maps) { maps.renderer = new SvgRenderer(maps.element.id); maps.availableSize = calculateSize(maps); maps.svgObject = maps.renderer.createSvg({ id: maps.element.id + '_svg', width: maps.availableSize.width, height: maps.availableSize.height }); if (maps.width === '0px' || maps.width === '0%' || maps.height === '0%' || maps.height === '0px') { maps.svgObject.setAttribute('height', '0'); maps.svgObject.setAttribute('width', '0'); } } /** * Method to get the mouse position. * * @param {number} pageX - Specifies the pageX. * @param {number} pageY - Specifies the pageY. * @param {Element} element - Specifies the element. * @returns {MapLocation} - Returns the location. * @private */ export function getMousePosition(pageX, pageY, element) { var elementRect = element.getBoundingClientRect(); var pageXOffset = element.ownerDocument.defaultView.pageXOffset; var pageYOffset = element.ownerDocument.defaultView.pageYOffset; var clientTop = element.ownerDocument.documentElement.clientTop; var clientLeft = element.ownerDocument.documentElement.clientLeft; var positionX = elementRect.left + pageXOffset - clientLeft; var positionY = elementRect.top + pageYOffset - clientTop; return new MapLocation((pageX - positionX), (pageY - positionY)); } /** * Method to convert degrees to radians. * * @param {number} deg Specifies the degree value * @returns {number} Returns the number * @private */ export function degreesToRadians(deg) { return deg * (Math.PI / 180); } /** * Convert radians to degrees method. * * @param {number} radian Specifies the radian value * @returns {number} Returns the number * @private */ export function radiansToDegrees(radian) { return radian * (180 / Math.PI); } /** * Method for converting from latitude and longitude values to points. * * @param {number} latitude - Specifies the latitude. * @param {number} longitude - Specifies the longitude. * @param {number} factor - Specifies the factor. * @param {LayerSettings} layer - Specifies the layer settings. * @param {Maps} mapModel - Specifies the maps. * @returns {Point} - Returns the point values. * @private */ export function convertGeoToPoint(latitude, longitude, factor, layer, mapModel) { var mapSize = new Size(mapModel.mapAreaRect.width, mapModel.mapAreaRect.height); var x; var y; var value; var lat; var lng; var temp; var longitudeMinMax = mapModel.baseMapBounds.longitude; var latitudeMinMax = mapModel.baseMapBounds.latitude; var latRadian = degreesToRadians(latitude); var lngRadian = degreesToRadians(longitude); var type = !isNullOrUndefined(mapModel.projectionType) ? mapModel.projectionType : 'Mercator'; var size = (mapModel.isTileMap) ? Math.pow(2, 1) * 256 : (isNullOrUndefined(factor)) ? Math.min(mapSize.width, mapSize.height) : (Math.min(mapSize.width, mapSize.height) * factor); if (layer.geometryType === 'Normal') { x = isNullOrUndefined(factor) ? longitude : Math.abs((longitude - longitudeMinMax.min) * factor); y = isNullOrUndefined(factor) ? latitude : Math.abs((latitudeMinMax.max - latitude) * factor); } else if (layer.geometryType === 'Geographic') { switch (type) { case 'Mercator': { var pixelOrigin = new Point(size / 2, size / 2); x = pixelOrigin.x + longitude * (size / 360); var sinY = calculateBound(Math.sin(degreesToRadians(latitude)), -0.9999, 0.9999); y = pixelOrigin.y + 0.5 * (Math.log((1 + sinY) / (1 - sinY))) * (-(size / (2 * Math.PI))); break; } case 'Winkel3': value = aitoff(lngRadian, latRadian); lng = (value.x + lngRadian / (Math.PI / 2)) / 2; lat = (value.y + latRadian) / 2; break; case 'Miller': lng = lngRadian; lat = (1.25 * Math.log(Math.tan((Math.PI / 4) + (.4 * latRadian)))); break; case 'Eckert3': temp = Math.sqrt(Math.PI * (4 + Math.PI)); lng = 2 / temp * lngRadian * (1 + Math.sqrt(1 - 4 * latRadian * latRadian / (Math.PI * Math.PI))); lat = 4 / temp * latRadian; break; case 'AitOff': value = aitoff(lngRadian, latRadian); lng = value.x; lat = value.y; break; case 'Eckert5': lng = lngRadian * (1 + Math.cos(latRadian)) / Math.sqrt(2 + Math.PI); lat = 2 * latRadian / Math.sqrt(2 + Math.PI); break; case 'Equirectangular': lng = lngRadian; lat = latRadian; break; case 'Eckert6': { var epsilon = 1e-6; temp = (1 + (Math.PI / 2)) * Math.sin(latRadian); var delta = Infinity; for (var i = 0; i < 10 && Math.abs(delta) > epsilon; i++) { delta = (latRadian + (Math.sin(latRadian)) - temp) / (1 + Math.cos(latRadian)); latRadian = latRadian - delta; } temp = Math.sqrt(2 + Math.PI); lng = lngRadian * (1 + Math.cos(latRadian)) / temp; lat = 2 * latRadian / temp; break; } } x = (type === 'Mercator') ? x : roundTo(xToCoordinate(mapModel, radiansToDegrees(lng)), 3); y = (type === 'Mercator') ? y : (-(roundTo(yToCoordinate(mapModel, radiansToDegrees(lat)), 3))); } return new Point(x, y); } /** * @param {Maps} maps - Specifies the map control. * @param {number} factor - Specifies the factor. * @param {LayerSettings} currentLayer - Specifies the current layer. * @param {Coordinate} markerData - Specifies the marker data. * @returns {string} - Returns the path. * @private */ export function calculatePolygonPath(maps, factor, currentLayer, markerData) { var path = ''; if (!isNullOrUndefined(markerData) && markerData.length > 1) { Array.prototype.forEach.call(markerData, function (data, dataIndex) { var lat = data.latitude; var lng = data.longitude; var location = (maps.isTileMap) ? convertTileLatLongToPoint(new MapLocation(lng, lat), factor, maps.tileTranslatePoint, true) : convertGeoToPoint(lat, lng, factor, currentLayer, maps); if (dataIndex === 0) { path += 'M ' + location.x + ' ' + location.y; } else { path += ' L ' + location.x + ' ' + location.y; } }); path += ' z '; } return path; } /** * Converting tile latitude and longitude to point. * * @param {MapLocation} center Specifies the map center location * @param {number} zoomLevel Specifies the zoom level * @param {MapLocation} tileTranslatePoint Specifies the tile translate point * @param {boolean} isMapCoordinates Specifies the boolean value * @returns {MapLocation} Returns the location value * @private */ export function convertTileLatLongToPoint(center, zoomLevel, tileTranslatePoint, isMapCoordinates) { var size = Math.pow(2, zoomLevel) * 256; var x = (center.x + 180) / 360; var sinLatitude = Math.sin(center.y * Math.PI / 180); var y = 0.5 - Math.log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * Math.PI); var pixelX = center.x; var pixelY = center.y; if (isMapCoordinates) { pixelX = (x * size + 0.5) + tileTranslatePoint.x; pixelY = (y * size + 0.5) + tileTranslatePoint.y; } return { x: pixelX, y: pixelY }; } /** * Method for calculate x point. * * @param {Maps} mapObject - Specifies the maps. * @param {number} val - Specifies the value. * @returns {number} - Returns the number. * @private */ export function xToCoordinate(mapObject, val) { var longitudeMinMax = mapObject.baseMapBounds.longitude; var totalSize = isNullOrUndefined(mapObject.baseSize) ? mapObject.mapAreaRect.width : mapObject.mapAreaRect.width + (Math.abs(mapObject.baseSize.width - mapObject.mapAreaRect.width) / 2); return Math.round(totalSize * (val - longitudeMinMax.min) / (longitudeMinMax.max - longitudeMinMax.min) * 100) / 100; } /** * Method for calculate y point. * * @param {Maps} mapObject - Specifies the maps. * @param {number} val - Specifies the value. * @returns {number} - Returns the number. * @private */ export function yToCoordinate(mapObject, val) { var latitudeMinMax = mapObject.baseMapBounds.latitude; return Math.round(mapObject.mapAreaRect.height * (val - latitudeMinMax.min) / (latitudeMinMax.max - latitudeMinMax.min) * 100) / 100; } /** * Method for calculate aitoff projection. * * @param {number} x - Specifies the x value. * @param {number} y - Specifies the y value. * @returns {Point} - Returns the point value. * @private */ export function aitoff(x, y) { var cosy = Math.cos(y); var sincia = sinci(acos(cosy * Math.cos(x /= 2))); return new Point(2 * cosy * Math.sin(x) * sincia, Math.sin(y) * sincia); } /** * Method to round the number. * * @param {number} a - Specifies the a value * @param {number} b - Specifies the b value * @returns {number} - Returns the number * @private */ export function roundTo(a, b) { var c = Math.pow(10, b); return (Math.round(a * c) / c); } /** * * @param {number} x - Specifies the x value * @returns {number} - Returns the number * @private */ export function sinci(x) { return x / Math.sin(x); } /** * * @param {number} a - Specifies the a value * @returns {number} - Returns the number * @private */ export function acos(a) { return Math.acos(a); } /** * Method to calculate bound. * * @param {number} value Specifies the value * @param {number} min Specifies the minimum value * @param {number} max Specifies the maximum value * @returns {number} Returns the value * @private */ export function calculateBound(value, min, max) { if (!isNullOrUndefined(min)) { value = Math.max(value, min); } if (!(isNullOrUndefined(max))) { value = Math.min(value, max); } return value; } /** * To trigger the download element. * * @param {string} fileName Specifies the file name * @param {ExportType} type Specifies the type * @param {string} url Specifies the url * @param {boolean} isDownload Specifies whether download a file. * @returns {void} * @private */ export function triggerDownload(fileName, type, url, isDownload) { createElement('a', { attrs: { 'download': fileName + '.' + type.toLocaleLowerCase(), 'href': url } }).dispatchEvent(new MouseEvent(isDownload ? 'click' : 'move', { view: window, bubbles: false, cancelable: true })); } /** * Specifies the information of the position of the point in maps. */ var Point = /** @class */ (function () { function Point(x, y) { this.x = x; this.y = y; } return Point; }()); export { Point }; /** * Specifies the position of the legend on the map, with options to set the * position values as percentages. The legend is placed relative to the Maps, * ensuring responsiveness. */ var RelativePoint = /** @class */ (function () { function RelativePoint(x, y) { this.x = x; this.y = y; } return RelativePoint; }()); export { RelativePoint }; /** * Defines the latitude and longitude values that define a map location. */ var Coordinate = /** @class */ (function () { function Coordinate(latitude, longitude) { this.latitude = latitude; this.longitude = longitude; } return Coordinate; }()); export { Coordinate }; /** * Map internal class for min and max * */ var MinMax = /** @class */ (function () { function MinMax(min, max) { this.min = min; this.max = max; } return MinMax; }()); export { MinMax }; /** * Map internal class locations */ var GeoLocation = /** @class */ (function () { function GeoLocation(latitude, longitude) { this.latitude = new MinMax(latitude.min, latitude.max); this.longitude = new MinMax(longitude.min, longitude.max); } return GeoLocation; }()); export { GeoLocation }; /** * Function to measure the height and width of the text. * * @param {string} text Specifies the text * @param {FontModel} font Specifies the font * @returns {Size} Returns the size * @private */ export function measureText(text, font) { var measureObject = document.getElementById('mapsmeasuretext'); if (measureObject === null) { measureObject = document.createElement('text'); measureObject.id = 'mapsmeasuretext'; document.body.appendChild(measureObject); } measureObject.innerText = text; measureObject.style.cssText = 'position: absolute; font-size: ' + (typeof (font.size) === 'number' ? (font.size + 'px') : font.size) + '; font-weight: ' + font.fontWeight + '; font-style: ' + font.fontStyle + '; font-family: ' + font.fontFamily + '; visibility: hidden; top: -100; left: 0; whiteSpace: nowrap; lineHeight: normal'; return new Size(measureObject.clientWidth, measureObject.clientHeight); } /** * @param {string} text - Specifies the text. * @param {FontModel} font - Specifies the font. * @returns {Size} - Returns the size of text. * @private */ export function measureTextElement(text, font) { var canvas = document.createElement('canvas'); // eslint-disable-next-line @typescript-eslint/tslint/config var context = canvas.getContext('2d'); context.font = font.fontStyle + " " + font.fontWeight + " " + (typeof font.size === 'number' ? font.size + 'px' : font.size) + " " + font.fontFamily; var metrics = context.measureText(text); var width = metrics.width; var height = parseFloat(font.size) || 16; canvas = null; return new Size(width, height); } /** * Internal use of text options. * * @private */ var TextOption = /** @class */ (function () { function TextOption(id, x, y, anchor, text, transform, baseLine) { if (transform === void 0) { transform = ''; } this.transform = ''; this.baseLine = 'auto'; this.id = id; this.text = text; this.transform = transform; this.anchor = anchor; this.x = x; this.y = y; this.baseLine = baseLine; } return TextOption; }()); export { TextOption }; /** * Internal use of path options. * * @private */ var PathOption = /** @class */ (function () { function PathOption(id, fill, width, color, fillOpacity, strokeOpacity, dashArray, d) { this.id = id; this['fill-opacity'] = fillOpacity; this['stroke-opacity'] = strokeOpacity; this.fill = fill; this.stroke = color; this['stroke-width'] = width; this['stroke-dasharray'] = dashArray; this.d = d; } return PathOption; }()); export { PathOption }; /** @private */ var ColorValue = /** @class */ (function () { function ColorValue(r, g, b) { this.r = r; this.g = g; this.b = b; } return ColorValue; }()); export { ColorValue }; /** * Internal use of rectangle options. * * @private */ var RectOption = /** @class */ (function (_super) { __extends(RectOption, _super); function RectOption(id, fill, border, fillOpacity, rect, rx, ry, transform, dashArray) { var _this = _super.call(this, id, fill, border.width, border.color, fillOpacity, border.opacity) || this; _this.y = rect.y; _this.x = rect.x; _this.height = rect.height; _this.width = rect.width; _this.rx = rx ? rx : 0; _this.ry = ry ? ry : 0; _this.transform = transform ? transform : ''; _this['stroke-dasharray'] = dashArray; _this['fill-opacity'] = fillOpacity; _this['stroke-opacity'] = border.opacity; return _this; } return RectOption; }(PathOption)); export { RectOption }; /** * Internal use of circle options. * * @private */ var CircleOption = /** @class */ (function (_super) { __extends(CircleOption, _super); function CircleOption(id, fill, border, fillOpacity, cx, cy, r, dashArray) { var _this = _super.call(this, id, fill, border.width, border.color, fillOpacity, border.opacity, dashArray) || this; _this.cy = cy; _this.cx = cx; _this.r = r; _this['stroke-dasharray'] = dashArray; _this['fill-opacity'] = fillOpacity; _this['stroke-opacity'] = border.opacity; return _this; } return CircleOption; }(PathOption)); export { CircleOption }; /** * Internal use of polygon options. * * @private */ var PolygonOption = /** @class */ (function (_super) { __extends(PolygonOption, _super); function PolygonOption(id, points, fill, width, color, fillOpacity, strokeOpacity, dashArray) { if (fillOpacity === void 0) { fillOpacity = 1; } if (strokeOpacity === void 0) { strokeOpacity = 1; } if (dashArray === void 0) { dashArray = ''; } var _this = _super.call(this, id, fill, width, color, fillOpacity, strokeOpacity, dashArray) || this; _this.points = points; return _this; } return PolygonOption; }(PathOption)); export { PolygonOption }; /** * Internal use of polyline options. * * @private */ var PolylineOption = /** @class */ (function (_super) { __extends(PolylineOption, _super); function PolylineOption(id, points, fill, width, color, fillOpacity, strokeOpacity, dashArray) { if (fillOpacity === void 0) { fillOpacity = 1; } if (strokeOpacity === void 0) { strokeOpacity = 1; } if (dashArray === void 0) { dashArray = ''; } return _super.call(this, id, points, fill, width, color, fillOpacity, strokeOpacity, dashArray) || this; } return PolylineOption; }(PolygonOption)); export { PolylineOption }; /** * Internal use of line options. * * @private */ var LineOption = /** @class */ (function (_super) { __extends(LineOption, _super); function LineOption(id, line, fill, width, color, fillOpacity, strokeOpacity, dashArray) { if (fillOpacity === void 0) { fillOpacity = 1; } if (strokeOpacity === void 0) { strokeOpacity = 1; } if (dashArray === void 0) { dashArray = ''; } var _this = _super.call(this, id, fill, width, color, fillOpacity, strokeOpacity, dashArray) || this; _this.x1 = line.x1; _this.y1 = line.y1; _this.x2 = line.x2; _this.y2 = line.y2; return _this; } return LineOption; }(PathOption)); export { LineOption }; /** * Internal use of line. * * @property {number} Line - Specifies the line class * @private */ var Line = /** @class */ (function () { function Line(x1, y1, x2, y2) { this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; } return Line; }()); export { Line }; /** * Internal use of map location type. * * @private */ var MapLocation = /** @class */ (function () { function MapLocation(x, y) { this.x = x; this.y = y; } return MapLocation; }()); export { MapLocation }; /** * Internal use of type rect. * * @private */ var Rect = /** @class */ (function () { function Rect(x, y, width, height) { this.x = x; this.y = y; this.width = width; this.height = height; } return Rect; }()); export { Rect }; /** * Internal use for pattern creation. * * @property {PatternOptions} PatternOptions - Specifies the pattern option class. * @private */ var PatternOptions = /** @class */ (function () { function PatternOptions(id, x, y, width, height, patternUnits, patternContentUnits, patternTransform, href) { if (patternUnits === void 0) { patternUnits = 'userSpaceOnUse'; } if (patternContentUnits === void 0) { patternContentUnits = 'userSpaceOnUse'; } if (patternTransform === void 0) { patternTransform = ''; } if (href === void 0) { href = ''; } this.id = id; this.x = x; this.y = y; this.width = width; this.height = height; this.patternUnits = patternUnits; this.patternContentUnits = patternContentUnits; this.patternTransform = patternTransform; this.href = href; } return PatternOptions; }()); export { PatternOptions }; /** * Internal rendering of text. * * @param {TextOption} option Specifies the text option * @param {FontModel} style Specifies the style * @param {string} color Specifies the color * @param {HTMLElement | Element} parent Specifies the parent element * @param {boolean} isMinus Specifies the boolean value * @returns {Element} Returns the html object * @private */ export function renderTextElement(option, style, color, parent, isMinus) { if (isMinus === void 0) { isMinus = false; } // eslint-disable-next-line @typescript-eslint/no-explicit-any var renderOptions = { 'id': option.id, 'x': option.x, 'y': option.y, 'fill': color, 'font-size': style.size, 'font-style': style.fontStyle, 'font-family': style.fontFamily, 'font-weight': style.fontWeight, 'text-anchor': option.anchor, 'transform': option.transform, 'opacity': style.opacity, 'dominant-baseline': option.baseLine }; var text = typeof option.text === 'string' || typeof option.text === 'number' ? option.text : isMinus ? option.text[option.text.length - 1] : option.text[0]; var tspanElement; var renderer = new SvgRenderer(''); var height; var htmlObject = renderer.createText(renderOptions, text); htmlObject.style['user-select'] = 'none'; htmlObject.style['font-family'] = style.fontFamily; htmlObject.style['font-size'] = style.size; htmlObject.style['font-weight'] = style.fontWeight; htmlObject.style['font-color'] = style.color; htmlObject.style['-moz-user-select'] = 'none'; htmlObject.style['-webkit-touch-callout'] = 'none'; htmlObject.style['-webkit-user-select'] = 'none'; htmlObject.style['-khtml-user-select'] = 'none'; htmlObject.style['-ms-user-select'] = 'none'; htmlObject.style['-o-user-select'] = 'none'; if (typeof option.text !== 'string' && option.text.length > 1) { for (var i = 1, len = option.text.length; i < len; i++) { height = (measureText(option.text[i], style).height); tspanElement = renderer.createTSpan({ 'x': option.x, 'id': option.id, 'y': (option.y) + ((isMinus) ? -(i * height) : (i * height)) }, isMinus ? option.text[option.text.length - (i + 1)] : option.text[i]); htmlObject.appendChild(tspanElement); } } parent.appendChild(htmlObject); return htmlObject; } /** * @param {HTMLCollection} element - Specifies the html collection * @param {string} markerId - Specifies the marker id * @param {object} data - Specifies the data * @param {number} index - Specifies the index * @param {Maps} mapObj - Specifies the map object * @param {string} templateType - Specifies the template type * @returns {HTMLElement} - Returns the html element * @private */ export function convertElement(element, markerId, data, index, mapObj, templateType) { var childElement = createElement('div', { id: markerId, className: mapObj.element.id + '_marker_template_element' }); childElement.style.cssText = 'position: absolute;pointer-events: auto;'; var elementLength = element.length; while (elementLength > 0) { childElement.appendChild(element[0]); elementLength--; } // eslint-disable-next-line @typescript-eslint/no-explicit-any if (!mapObj.isReact || templateType !== 'function') { var templateHtml = childElement.innerHTML; var properties = Object.keys(data); var regExp = RegExp; for (var i = 0; i < properties.length; i++) { if (typeof data[properties[i]] === 'object') { templateHtml = convertStringToValue(templateHtml, '', data, mapObj); // eslint-disable-next-line @typescript-eslint/ban-types } else if (properties[i].toLowerCase() !== 'latitude' && properties[i].toLowerCase() !== 'longitude') { templateHtml = templateHtml.replace(new regExp('{{:' + properties[i] + '}}', 'g'), data[properties[i].toString()]); } } childElement.innerHTML = templateHtml; } return childElement; } /** * * @param {string} value - Specifies the value * @param {Maps} maps - Specifies the instance of the maps * @returns {string} - Returns the string value * @private */ export function formatValue(value, maps) { // eslint-disable-next-line @typescript-eslint/no-explicit-any var formatValue; var formatFunction; if (maps.format && !isNaN(Number(value))) { formatFunction = maps.intl.getNumberFormat({ format: maps.format, useGrouping: maps.useGroupingSeparator }); formatValue = formatFunction(Number(value)); } else { formatValue = value; } return formatValue; } /** * * @param {string} stringTemplate - Specifies the template * @param {string} format - Specifies the format * @param {object} data - Specifies the data * @param {Maps} maps - Specifies the instance of the maps * @returns {string} - Returns the string value * @private */ export function convertStringToValue(stringTemplate, format, data, maps) { var templateHtml = (stringTemplate === '') ? format : stringTemplate; var templateValue = (stringTemplate === '') ? templateHtml.split('${') : templateHtml.split('{{:'); var regExp = RegExp; for (var i = 0; i < templateValue.length; i++) { if ((templateValue[i].indexOf('}}') > -1 && templateValue[i].indexOf('.') > -1) || (templateValue[i].indexOf('}') > -1 && templateValue[i].search('.') > -1)) { var split = (stringTemplate === '') ? templateValue[i].split('}') : templateValue[i].split('}}'); for (var j = 0; j < split.length; j++) { if (split[j].indexOf('.') > -1) { var templateSplitValue = (getValueFromObject(data, split[j])).toString(); templateHtml = (stringTemplate === '') ? templateHtml.split('${' + split[j] + '}').join(formatValue(templateSplitValue, maps)) : templateHtml.replace(new regExp('{{:' + split[j] + '}}', 'g'), templateSplitValue); } } } } return templateHtml; } /** * * @param {Element} element - Specifies the element * @param {string} labelId - Specifies the label id * @param {object} data - Specifies the data * @returns {HTMLElement} - Returns the html element * @private */ export function convertElementFromLabel(element, labelId, data) { var labelEle = isNullOrUndefined(element.childElementCount) ? element[0] : element; var templateHtml = labelEle.outerHTML; // eslint-disable-next-line @typescript-eslint/no-explicit-any var properties = Object.keys(data); var regExp = RegExp; for (var i = 0; i < properties.length; i++) { // eslint-disable-next-line @typescript-eslint/ban-types templateHtml = templateHtml.replace(new regExp('{{:' + properties[i] + '}}', 'g'), data[properties[i].toString()]); } var templateEle = createElement('div', { id: labelId, innerHTML: templateHtml }); templateEle.style.position = 'absolute'; return templateEle; } /** * * @param {MarkerType} shape - Specifies the shape * @param {string} imageUrl - Specifies the image url * @param {Point} location - Specifies the location * @param {string} markerID - Specifies the marker id * @param {any} shapeCustom - Specifies the shape custom * @param {Element} markerCollection - Specifies the marker collection * @param {Maps} maps - Specifies the instance of the maps * @returns {Element} - Returns the element * @private */ // eslint-disable-next-line @typescript-eslint/no-explicit-any export function drawSymbols(shape, imageUrl, location, markerID, shapeCustom, markerCollection, maps) { var markerEle; var x; var y; var size = shapeCustom['size']; var borderColor = shapeCustom['borderColor']; var borderWidth = parseFloat(shapeCustom['borderWidth']); var borderOpacity = parseFloat(shapeCustom['borderOpacity']); var fill = shapeCustom['fill']; var dashArray = shapeCustom['dashArray']; // eslint-disable-next-line @typescript-eslint/no-explicit-any var border = { color: borderColor, width: borderWidth, opacity: borderOpacity }; var opacity = shapeCustom['opacity']; var rectOptions; var pathOptions = new PathOption(markerID, fill, borderWidth, borderColor, opacity, borderOpacity, dashArray, ''); size.width = typeof (size.width) === 'string' ? parseInt(size.width, 10) : size.width; size.height = typeof (size.height) === 'string' ? parseInt(size.height, 10) : size.height; if (shape === 'Circle') { var radius = (size.width + size.height) / 4; var circleOptions = new CircleOption(markerID, fill, border, opacity, location.x, location.y, radius, dashArray); markerEle = maps.renderer.drawCircle(circleOptions); } else if (shape === 'Rectangle') { x = location.x - (size.width / 2); y = location.y - (size.height / 2); rectOptions = new RectOption(markerID, fill, border, opacity, new Rect(x, y, size.width, size.height), null, null, '', dashArray); markerEle = maps.renderer.drawRectangle(rectOptions); } else if (shape === 'Image') { x = location.x - (size.width / 2); y = location.y - (markerID.indexOf('cluster') > -1 ? (size.height / 2) : size.height); merge(pathOptions, { 'href': imageUrl, 'height': size.height, 'width': size.width, x: x, y: y }); markerEle = maps.renderer.drawImage(pathOptions); } else { markerEle = calculateShapes(maps, shape, pathOptions, size, location, markerCollection); } return markerEle; } /** * * @param {object} data - Specifies the data * @param {string} value - Specifies the value * @returns {any} - Returns the data * @private */ // eslint-disable-next-line @typescript-eslint/no-explicit-any export function getValueFromObject(data, value) { if (!isNullOrUndefined(data) && !isNullOrUndefined(value)) { var splits = value.replace(/\[/g, '.').replace(/\]/g, '').split('.'); if (splits.length === 1) { data = data[splits[0]]; } else { for (var i = 0; i < splits.length && !isNullOrUndefined(data); i++) { data = data[splits[i]]; } } } return data; } /** * * @param {IMarkerRenderingEventArgs} eventArgs - Specifies the event arguments * @param {object} data - Specifies the data * @returns {IMarkerRenderingEventArgs} - Returns the arguments * @private */ export function markerColorChoose(eventArgs, data) { var color = (!isNullOrUndefined(eventArgs.colorValuePath)) ? ((eventArgs.colorValuePath.indexOf('.') > -1) ? (getValueFromObject(data, eventArgs.colorValuePath)).toString() : data[eventArgs.colorValuePath]) : data[eventArgs.colorValuePath]; eventArgs.fill = (!isNullOrUndefined(eventArgs.colorValuePath) && !isNullOrUndefined(color)) ? ((eventArgs.colorValuePath.indexOf('.') > -1) ? (getValueFromObject(data, eventArgs.colorValuePath)).toString() : data[eventArgs.colorValuePath]) : eventArgs.fill; return eventArgs; } /** * * @param {IMarkerRenderingEventArgs} eventArgs - Specifies the event arguments * @param {object} data - Specifies the data * @returns {IMarkerRenderingEventArgs} - Returns the arguments * @private */ export function markerShapeChoose(eventArgs, data) { if (!isNullOrUndefined(eventArgs.shapeValuePath) && !isNullOrUndefined(data[eventArgs.shapeValuePath])) { updateShape(eventArgs, data); if (data[eventArgs.shapeValuePath] === 'Image') { updateImageUrl(eventArgs, data); } } else { updateShape(eventArgs, data); updateImageUrl(eventArgs, data); } return eventArgs; } /** * * @param {any} path - contains a dot, it implies that the desired property is nested within the object. * @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. * @returns {any} - Returns the value of the property specified in the path. * @private */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function getValue(path, data) { return (path.indexOf('.') > -1) ? getValueFromObject(data, path).toString() : data[path]; } /** * * @param {any} eventArgs - Specifies the event arguments * @param {any} data - Specifies the data * @private */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function updateShape(eventArgs, data) { if (!isNullOrUndefined(eventArgs.shapeValuePath)) { var shape = getValue(eventArgs.shapeValuePath, data); eventArgs.shape = (!isNullOrUndefined(shape) && shape.toString() !== '') ? shape : eventArgs.shape; } } /** * * @param {any} eventArgs - Specifies the event arguments * @param {any} data - Specifies the data * @private */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function updateImageUrl(eventArgs, data) { if (!isNullOrUndefined(eventArgs.imageUrlValuePath)) { var imageUrl = getValue(eventArgs.imageUrlValuePath, data); eventArgs.imageUrl = (!isNullOrUndefined(imageUrl)) ? imageUrl : eventArgs.imageUrl; } } /** * * @param {LayerSettings} currentLayer - Specifies the current layer * @param {HTMLElement | Element} markerTemplate - Specifies the marker template * @param {Maps} maps - Specifies the instance of the maps * @param {number} layerIndex - Specifies the layer index * @param {number} markerIndex - Specifies the marker index * @param {Element} markerCollection - Specifies the marker collection * @param {Element} layerElement - Specifies the layer element * @param {boolean} check - Specifies the boolean value * @param {boolean} zoomCheck - Specifies the boolean value * @param {any} translatePoint - Specifies the data * @param {boolean} allowInnerClusterSetting - Specifies the boolean value * @returns {boolean} -Returns boolean for cluster completion * @private */ export function clusterTemplate(currentLayer, markerTemplate, maps, layerIndex, markerIndex, markerCollection, // eslint-disable-next-line @typescript-eslint/no-explicit-any layerElement, check, zoomCheck, translatePoint, allowInnerClusterSetting) { var bounds1; var bounds2; var colloideBounds = []; var clusterColloideBounds = []; var tempX = 0; var tempY = 0; // eslint-disable-next-line @typescript-eslint/no-explicit-any var data; var markerSetting = currentLayer.markerSettings[markerIndex]; var options; var textElement; var tempElement1; // eslint-disable-next-line @typescript-eslint/no-explicit-any var shapeCustom; var tempElement; var postionY = (15 / 4); var m = 0; var indexCollection = []; var clusters = !allowInnerClusterSetting && currentLayer.markerClusterSettings.allowClustering ? currentLayer.markerClusterSettings : markerSetting.clusterSettings; var style = clusters.labelStyle; var clusterGroup = maps.renderer.createGroup({ id: maps.element.id + '_LayerIndex_' + layerIndex + '_markerCluster' }); var eventArg = { cancel: false, name: markerClusterRendering, fill: clusters.fill, height: clusters.height, width: clusters.width, imageUrl: clusters.imageUrl, shape: clusters.shape, data: data, maps: maps, cluster: clusters, border: clusters.border }; var containerRect = maps.element.getBoundingClientRect(); // eslint-disable-next-line @typescript-eslint/no-unused-expressions (maps.isTileMap) ? new Object() : getTranslate(maps, currentLayer, false); var factor; if (!maps.isTileMap) { factor = maps.mapLayerPanel.calculateFactor(currentLayer); } var isClusteringCompleted = false; var currentZoomFactor = !maps.isTileMap ? maps.mapScaleValue : maps.tileZoomLevel; var markerGroup = (markerSetting.clusterSettings.allowClustering || (currentLayer.markerClusterSettings.allowClustering && currentLayer.markerSettings.length > 1)) ? markerTemplate.querySelectorAll("[id*='LayerIndex_" + layerIndex + "_MarkerIndex_" + markerIndex + "']:not([id*='_Group'])") : markerTemplate.childNodes; // eslint-disable-next-line @typescript-eslint/no-unused-vars maps.trigger('markerClusterRendering', eventArg, function (clusterargs) { Array.prototype.forEach.call(markerGroup, function (markerElement, o) { indexCollection = []; if (markerElement['style']['visibility'] !== 'hidden') { tempElement = markerElement; bounds1 = tempElement.getBoundingClientRect(); indexCollection.push(o); if (!isNullOrUndefined(bounds1)) { var list = (maps.markerModule.zoomedMarkerCluster.length > 0 && maps.markerModule.zoomedMarkerCluster[layerIndex] && maps.markerModule.zoomedMarkerCluster[layerIndex][o] && maps.markerModule.zoomedMarkerCluster[layerIndex][o].length > 0) || (maps.markerModule.initialMarkerCluster.length > 0 && maps.markerModule.initialMarkerCluster[layerIndex] && maps.markerModule.initialMarkerCluster[layerIndex][o] && maps.markerModule.initialMarkerCluster[layerIndex][o].length > 0) ? (maps.previousScale < currentZoomFactor ? maps.markerModule.zoomedMarkerCluster[layerIndex][o] : maps.markerModule.initialMarkerCluster[layerIndex][o]) : null; if (!isNullOrUndefined(list) && list.length !== 0 && !markerSetting.clusterSettings.allowClustering) { Array.prototype.forEach.call(list, function (currentIndex) { if (o !== currentIndex) { var otherMarkerElement = document.getElementById(maps.element.id + '_LayerIndex_' + layerIndex + '_MarkerIndex_' + markerIndex + '_dataIndex_' + currentIndex); if (otherMarkerElement && otherMarkerElement['style']['visibility'] !== 'hidden') { markerBoundsComparer(otherMarkerElement, bounds1, colloideBounds, indexCollection, currentIndex); } } }); } else { Array.prototype.forEach.call(markerGroup, function (otherMarkerElement, p) { if (p >= o + 1 && otherMarkerElement['style']['visibility'] !== 'hidden') { markerBoundsComparer(otherMarkerElement, bounds1, colloideBounds, indexCollection, p); } }); } markerClusterListHandler(maps, currentZoomFactor, layerIndex, o, indexCollection); tempX = bounds1.left + bounds1.width / 2; tempY = bounds1.top + bounds1.height; if (colloideBounds.length > 0) { // eslint-disable-next-line @typescript-eslint/no-explicit-any indexCollection = indexCollection.filter(function (item, index, value) { return value.indexOf(item) === index; }); tempX = tempX - containerRect['left']; tempY = (tempY - ((maps.availableSize.height <= containerRect['height']) ? containerRect['top'] : (containerRect['bottom'] - containerRect['top']))); var dataIndex = parseInt(markerElement['id'].split('_dataIndex_')[1].split('_')[0], 10); var markerIndex_1 = parseInt(markerElement['id'].split('_MarkerIndex_')[1].split('_')[0], 10); var markerSetting_1 = currentLayer.markerSettings[markerIndex_1]; // eslint-disable-next-line @typescript-eslint/no-explicit-any var markerData = markerSetting_1.dataSource[dataIndex]; var location_1; var longitude = (!isNullOrUndefined(markerSetting_1.longitudeValuePath)) ? Number(getValueFromObject(markerData, markerSetting_1.longitudeValuePath)) : !isNullOrUndefined(markerData['longitude']) ? parseFloat(markerData['longitude']) : !isNullOrUndefined(markerData['Longitude']) ? parseFloat(markerData['Longitude']) : 0; var latitude = (!isNullOrUndefined(markerSetting_1.latitudeValuePath)) ? Number(getValueFromObject(markerData, markerSetting_1.latitudeValuePath)) : !isNullOrUndefined(markerData['latitude']) ? parseFloat(markerData['latitude']) : !isNullOrUndefined(markerData['Latitude']) ? parseFloat(markerData['Latitude']) : 0; if (!maps.isTileMap) { location_1 = convertGeoToPoint(latitude, longitude, factor, currentLayer, maps); } else if (maps.isTileMap) { location_1 = convertTileLatLongToPoint(new Point(longitude, latitude), maps.tileZoomLevel, maps.tileTranslatePoint, true); } markerElement['style']['visibility'] = 'hidden'; if (eventArg.cancel) { shapeCustom = { size: new Size(clusters.width, clusters.height), fill: clusters.fill, borderColor: clusters.border.color, borderWidth: clusters.border.width, opacity: clusters.opacity, dashArray: clusters.dashArray, imageUrl: clusters.imageUrl, shape: clusters.shape }; shapeCustom['borderOpacity'] = isNullOrUndefined(clusters.border.opacity) ? clusters.opacity : clusters.border.opacity; } else { shapeCustom = { size: new Size(eventArg.width, eventArg.height), fill: eventArg.fill, borderColor: eventArg.border.color, borderWidth: eventArg.border.width, opacity: clusters.opacity, dashArray: clusters.dashArray, imageUrl: eventArg.imageUrl, shape: eventArg.shape }; shapeCustom['borderOpacity'] = isNullOrUndefined(eventArg.border.opacity) ? clusters.opacity : eventArg.border.opacity; } tempX = (maps.isTileMap) ? tempX : (markerTemplate.id.indexOf('_Markers_Group') > -1) ? tempX : tempX + postionY - (eventArg.width / 2); tempY = (maps.isTileMap) ? tempY : (markerTemplate.id.indexOf('_Markers_Group') > -1) ? tempY : tempY - (eventArg.height / 2); if (maps.isTileMap) { tempX = location_1.x; tempY = location_1.y; } else { tempX = (((location_1.x + ((!isNullOrUndefined(maps.translatePoint) && maps.translatePoint.x !== 0 && !maps.isResize) ? maps.translatePoint.x : translatePoint.location.x)) * (isNullOrUndefined(maps.scale) ? translatePoint.scale : maps.scale)) + markerSetting_1.offset.x); tempY = (((location_1.y + ((!isNullOrUndefined(maps.translatePoint) && maps.translatePoint.y !== 0 && !maps.isResize) ? maps.translatePoint.y : translatePoint.location.y)) * (isNullOrUndefined(maps.scale) ? translatePoint.scale : maps.scale)) + markerSetting_1.offset.y); } var clusterID = maps.element.id + '_LayerIndex_' + layerIndex + '_MarkerIndex_' + markerIndex_1 + '_dataIndex_' + dataIndex + '_cluster_' + (m); var labelID = maps.element.id + '_LayerIndex_' + layerIndex + '_MarkerIndex_' + markerIndex_1 + '_dataIndex_' + dataIndex + '_cluster_' + (m) + '_datalabel_' + m; m++; var ele = drawSymbols(shapeCustom['shape'], shapeCustom['imageUrl'], { x: 0, y: 0 }, clusterID, shapeCustom, markerCollection, maps); ele.setAttribute('transform', 'translate( ' + tempX + ' ' + tempY + ' )'); if (eventArg.shape === 'Balloon') { ele.children[0].textContent = indexCollection.toString(); } else { ele.textContent = indexCollection.toString(); } options = new TextOption(labelID, (0), postionY, 'middle', (colloideBounds.length + 1).toString(), '', ''); textElement = renderTextElement(options, style, style.color, markerCollection); textElement.setAttribute('transform', 'translate( ' + tempX + ' ' + tempY + ' )'); var eleMarkerIndex = parseFloat(ele.id.split('_MarkerIndex_')[1]); if ((markerSetting_1.clusterSettings.allowClustering && eleMarkerIndex === markerIndex_1) || (currentLayer.markerClusterSettings.allowClustering && currentLayer.markerSettings.length > 1 && eleMarkerIndex === markerIndex_1)) { clusterGroup.appendChild(ele); clusterGroup.appendChild(textElement); } else { clusterGroup.appendChild(textElement);