@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
JavaScript
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);