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

814 lines (805 loc) 87.7 kB
/* eslint-disable no-case-declarations */ import { isNullOrUndefined, extend, createElement, Fetch, animationMode } from '@syncfusion/ej2-base'; import { Maps } from '../../maps/maps'; import { getShapeColor } from '../model/theme'; import { GeoLocation, isCustomPath, convertGeoToPoint, Point, PathOption, Size, removeElement, maintainToggleSelection } from '../utils/helper'; import { getElementByID, maintainSelection, getValueFromObject } from '../utils/helper'; import { MapLocation, RectOption, getTranslate, convertTileLatLongToPoint, checkShapeDataFields, CircleOption } from '../utils/helper'; import { getZoomTranslate, fixInitialScaleForTile } from '../utils/helper'; import { LayerSettings, ShapeSettings, Tile} from '../model/base'; import { BorderModel, LayerSettingsModel } from '../model/base-model'; import { BingMap } from './bing-map'; import { ColorMapping } from './color-mapping'; import { layerRendering, ILayerRenderingEventArgs, shapeRendering, IShapeRenderingEventArgs, BubbleSettingsModel, Rect } from '../index'; /** * To calculate and render the shape layer */ export class LayerPanel { private mapObject: Maps; public currentFactor: number; private groupElements: Element[]; private layerObject: Element; private currentLayer: LayerSettings; // eslint-disable-next-line @typescript-eslint/no-explicit-any private rectBounds: any; public tiles: Tile[]; private clipRectElement: Element; private urlTemplate: string; private isMapCoordinates: boolean = true; private tileSvgObject: Element; private ajaxModule: Fetch; private ajaxResponse: LayerSettings[]; private bing: BingMap; private animateToZoomX : number; private animateToZoomY : number; public horizontalPan: boolean = false; public horizontalPanXCount: number = 0; public layerGroup: Element; constructor(map: Maps) { this.mapObject = map; this.ajaxModule = new Fetch(); this.ajaxResponse = []; } public measureLayerPanel(): void { const layerCollection: LayerSettings[] = <LayerSettings[]>this.mapObject.layersCollection; const areaRect: Rect = this.mapObject.mapAreaRect; const secondaryEle: HTMLElement = <HTMLElement>getElementByID(this.mapObject.element.id + '_Secondary_Element'); if (this.mapObject.isTileMap && secondaryEle) { this.tileSvgObject = this.mapObject.renderer.createSvg({ id: this.mapObject.element.id + '_Tile_SVG', width: areaRect.width, height: areaRect.height }); const parentElement: Element = createElement('div', { id: this.mapObject.element.id + '_Tile_SVG_Parent' }); (parentElement as HTMLElement).style.cssText = 'position: absolute; height: ' + (areaRect.height) + 'px; width: ' + (areaRect.width) + 'px;'; parentElement.appendChild(this.tileSvgObject); secondaryEle.appendChild(parentElement); } this.layerGroup = (this.mapObject.renderer.createGroup({ id: this.mapObject.element.id + '_Layer_Collections', 'clip-path': 'url(#' + this.mapObject.element.id + '_MapArea_ClipRect)' })); this.clipRectElement = this.mapObject.renderer.drawClipPath(new RectOption( this.mapObject.element.id + '_MapArea_ClipRect', 'transparent', { width: 1, color: 'Gray' }, 1, { x: this.mapObject.isTileMap ? 0 : areaRect.x, y: this.mapObject.isTileMap ? 0 : areaRect.y, width: areaRect.width, height: areaRect.height })); this.layerGroup.appendChild(this.clipRectElement); this.mapObject.baseMapBounds = null; this.mapObject.baseMapRectBounds = null; this.mapObject.baseSize = null; Array.prototype.forEach.call(layerCollection, (layer: LayerSettings, index: number) => { this.currentLayer = <LayerSettings>layer; this.processLayers(layer, index); }); if (!isNullOrUndefined(this.mapObject.legendModule) && this.mapObject.legendSettings.position === 'Float') { if (this.mapObject.isTileMap) { this.layerGroup.appendChild(this.mapObject.legendModule.legendGroup); } else { this.mapObject.svgObject.appendChild(this.mapObject.legendModule.legendGroup); } } } /** * Tile rendering * * @param {LayerPanel} panel - Specifies the layer panel. * @param {LayerSettings} layer - Specifies the layer settings. * @param {number} layerIndex - Specifies the layer index. * @param {BingMap} bing - Specifies the bing map. * @returns {void} * @private */ public renderTileLayer(panel: LayerPanel, layer: LayerSettings, layerIndex: number, bing?: BingMap): void { panel.currentFactor = panel.calculateFactor(layer); panel.mapObject.defaultState = ((panel.mapObject.zoomSettings.zoomFactor !== 1) && (!isNullOrUndefined(panel.mapObject.tileZoomLevel) && panel.mapObject.tileZoomLevel !== 1 )) ? false : true; if (isNullOrUndefined(panel.mapObject.previousCenterLatitude) && isNullOrUndefined(panel.mapObject.previousCenterLongitude) && !panel.mapObject.isZoomByPosition) { panel.mapObject.previousCenterLatitude = panel.mapObject.centerPosition.latitude; panel.mapObject.previousCenterLongitude = panel.mapObject.centerPosition.longitude; } else if ((panel.mapObject.previousCenterLatitude !== panel.mapObject.centerPosition.latitude && panel.mapObject.previousCenterLongitude !== panel.mapObject.centerPosition.longitude) || panel.mapObject.isZoomByPosition) { panel.mapObject.centerPositionChanged = true; panel.mapObject.previousCenterLatitude = panel.mapObject.centerPosition.latitude; panel.mapObject.previousCenterLongitude = panel.mapObject.centerPosition.longitude; } else { panel.mapObject.centerPositionChanged = false; } let center: Point = new Point(panel.mapObject.centerPosition.longitude, panel.mapObject.centerPosition.latitude); let centerTileMap : Point = center; if ((this.mapObject.isTileMap && panel.mapObject.markerModule) && panel.mapObject.zoomSettings.enable) { panel.mapObject.markerModule.calculateZoomCenterPositionAndFactor(this.mapObject.layersCollection); if (!isNullOrUndefined(this.mapObject.markerCenterLatitude) && !isNullOrUndefined(this.mapObject.markerCenterLongitude) && !panel.mapObject.isZoomByPosition) { centerTileMap = new Point(panel.mapObject.markerCenterLongitude, panel.mapObject.markerCenterLatitude); } } if (!panel.mapObject.zoomSettings.shouldZoomInitially && panel.mapObject.centerPosition.longitude && panel.mapObject.centerPosition.latitude && !panel.mapObject.zoomPersistence && panel.mapObject.defaultState) { center = new Point(panel.mapObject.centerPosition.longitude, panel.mapObject.centerPosition.latitude); } else if (panel.mapObject.zoomSettings.shouldZoomInitially && panel.mapObject.markerZoomedState && !panel.mapObject.zoomPersistence && !isNullOrUndefined(panel.mapObject.markerZoomCenterPoint)) { center = new Point(panel.mapObject.markerZoomCenterPoint.longitude, panel.mapObject.markerZoomCenterPoint.latitude); } else { center = { x: null, y: null }; } let zoomFactorValue: number = (panel.mapObject.zoomSettings.shouldZoomInitially && !panel.mapObject.isZoomByPosition) ? isNullOrUndefined(panel.mapObject.markerZoomFactor) ? 1 : panel.mapObject.markerZoomFactor : panel.mapObject.zoomSettings.zoomFactor; zoomFactorValue = (panel.mapObject.enablePersistence) ? ((isNullOrUndefined(panel.mapObject.mapScaleValue)) ? (isNullOrUndefined(panel.mapObject.markerZoomFactor) ? panel.mapObject.zoomSettings.zoomFactor : panel.mapObject.markerZoomFactor) : panel.mapObject.mapScaleValue) : zoomFactorValue; zoomFactorValue = panel.mapObject.zoomSettings.enable ? zoomFactorValue : panel.mapObject.zoomSettings.zoomFactor; zoomFactorValue = zoomFactorValue > 0 ? zoomFactorValue : 1; panel.mapObject.defaultState = zoomFactorValue !== 1 ? false : true; if (!panel.mapObject.markerZoomedState && panel.mapObject.zoomSettings.shouldZoomInitially && panel.mapObject.zoomSettings.zoomFactor === 1) { panel.mapObject.defaultState = true; } if (isNullOrUndefined(panel.mapObject.tileZoomLevel)) { panel.mapObject.tileZoomLevel = zoomFactorValue; panel.mapObject.previousZoomFactor = zoomFactorValue; } else if (this.mapObject.isReset && panel.mapObject.tileZoomLevel === 1 && !panel.mapObject.zoomSettings.shouldZoomInitially) { const zoomLevel: number = panel.mapObject.tileZoomLevel; panel.mapObject.tileZoomLevel = zoomLevel; } else if (panel.mapObject.zoomSettings.zoomFactor !== 1 || panel.mapObject.zoomSettings.shouldZoomInitially) { panel.mapObject.previousZoomFactor = panel.mapObject.tileZoomLevel; panel.mapObject.tileZoomLevel = panel.mapObject.defaultState && panel.mapObject.zoomSettings.enable ? panel.mapObject.tileZoomLevel : !panel.mapObject.zoomSettings.shouldZoomInitially && !panel.mapObject.centerPositionChanged ? panel.mapObject.previousZoomFactor !== panel.mapObject.zoomSettings.zoomFactor ? panel.mapObject.zoomSettings.zoomFactor : panel.mapObject.tileZoomLevel : zoomFactorValue; panel.mapObject.tileZoomLevel = zoomFactorValue === 1 && panel.mapObject.zoomSettings.zoomFactor === 0 ? zoomFactorValue : panel.mapObject.tileZoomLevel; if (!isNullOrUndefined(panel.mapObject.tileTranslatePoint) && (panel.mapObject.markerZoomFactor !== panel.mapObject.mapScaleValue || (isNullOrUndefined(panel.mapObject.markerZoomFactor) && isNullOrUndefined(panel.mapObject.mapScaleValue))) && (panel.mapObject.zoomSettings.zoomFactor <= 1 || panel.mapObject.previousZoomFactor !== panel.mapObject.zoomSettings.zoomFactor)) { panel.mapObject.tileTranslatePoint.x = 0; panel.mapObject.tileTranslatePoint.y = 0; } } else if (panel.mapObject.defaultState) { panel.mapObject.previousZoomFactor = panel.mapObject.tileZoomLevel; panel.mapObject.tileZoomLevel = zoomFactorValue; if (!isNullOrUndefined(panel.mapObject.tileTranslatePoint)) { panel.mapObject.tileTranslatePoint.x = 0; panel.mapObject.tileTranslatePoint.y = 0; } } if ( zoomFactorValue <= 1 && !isNullOrUndefined(panel.mapObject.height) && !panel.mapObject.zoomSettings.shouldZoomInitially && (panel.mapObject.tileZoomLevel === panel.mapObject.tileZoomScale) && this.mapObject.initialCheck ) { fixInitialScaleForTile(this.mapObject); } if (!isNullOrUndefined(panel.mapObject.centerLatOfGivenLocation) && !isNullOrUndefined(panel.mapObject.centerLongOfGivenLocation) && panel.mapObject.zoomNotApplied) { if (!isNullOrUndefined(centerTileMap)) { centerTileMap.y = panel.mapObject.centerLatOfGivenLocation; centerTileMap.x = panel.mapObject.centerLongOfGivenLocation; } panel.mapObject.tileZoomLevel = panel.mapObject.mapScaleValue = panel.mapObject.scaleOfGivenLocation; } panel.mapObject.tileTranslatePoint = panel.panTileMap( panel.mapObject.availableSize.width, panel.mapObject.availableSize.height, centerTileMap ); if (this.mapObject.zoomSettings.resetToInitial && this.mapObject.initialCheck && !isNullOrUndefined(panel.mapObject.height) && this.mapObject.availableSize.height > 512) { this.mapObject.applyZoomReset = true; this.mapObject.initialZoomLevel = Math.floor(this.mapObject.availableSize.height / 512); const padding : number = 20; const totalSize : number = Math.pow(2, this.mapObject.initialZoomLevel) * 256; if (!isNullOrUndefined(this.mapObject.initialTileTranslate)) { this.mapObject.initialTileTranslate.x = (this.mapObject.availableSize.width / 2) - (totalSize / 2); this.mapObject.initialTileTranslate.y = (this.mapObject.availableSize.height / 2) - (totalSize / 2) + padding; } } panel.generateTiles(panel.mapObject.tileZoomLevel, panel.mapObject.tileTranslatePoint, null, bing); if (!isNullOrUndefined(panel.mapObject.previousZoomFactor) && panel.mapObject.previousZoomFactor !== panel.mapObject.zoomSettings.zoomFactor) { panel.mapObject.previousZoomFactor = panel.mapObject.zoomSettings.zoomFactor; } if (panel.mapObject.polygonModule) { const polygonElement: Element = panel.mapObject.polygonModule.polygonRender(this.mapObject, layerIndex, panel.mapObject.tileZoomLevel); if (!isNullOrUndefined(polygonElement)) { panel.layerObject.appendChild(polygonElement); } } if (panel.mapObject.navigationLineModule) { const navigationLineElement: Element = panel.mapObject.navigationLineModule.renderNavigation(panel.currentLayer, panel.mapObject.tileZoomLevel, layerIndex); if (!isNullOrUndefined(navigationLineElement)) { panel.layerObject.appendChild(navigationLineElement); } } if (panel.mapObject.markerModule) { panel.mapObject.markerModule.markerRender(this.mapObject, panel.layerObject, layerIndex, panel.mapObject.tileZoomLevel, null); } panel.translateLayerElements(panel.layerObject); panel.layerGroup.appendChild(panel.layerObject); } protected processLayers(layer: LayerSettings, layerIndex: number): void { this.layerObject = (this.mapObject.renderer.createGroup({ id: this.mapObject.element.id + '_LayerIndex_' + layerIndex })); if (!this.mapObject.enablePersistence) { const itemName: string = this.mapObject.getModuleName() + this.mapObject.element.id; if (navigator.userAgent.indexOf('Edge') === -1) { // eslint-disable-next-line @typescript-eslint/no-explicit-any let data: any; try { data = window.localStorage; } catch (e) { data = null; } if (!isNullOrUndefined(data) && window.localStorage.getItem(itemName)) { window.localStorage.removeItem(itemName); } } } const eventArgs: ILayerRenderingEventArgs = { cancel: false, name: layerRendering, index: layerIndex, layer: layer, maps: this.mapObject, visible: layer.visible }; // eslint-disable-next-line @typescript-eslint/no-unused-vars this.mapObject.trigger('layerRendering', eventArgs, (observedArgs: ILayerRenderingEventArgs) => { if (!eventArgs.cancel && eventArgs.visible) { if ((isNullOrUndefined(layer.shapeData) && !isNullOrUndefined(layer.urlTemplate) && layer.urlTemplate !== '')) { if (!isNullOrUndefined(layer.urlTemplate) && layer.urlTemplate.indexOf('quadkey') > -1) { const bing: BingMap = new BingMap(this.mapObject); this.bingMapCalculation(layer, layerIndex, this, bing); } else { this.renderTileLayer(this, layer, layerIndex); } } else { if (!isNullOrUndefined(layer.shapeData) && (!isNullOrUndefined(layer.shapeData['geometries']) || !isNullOrUndefined(layer.shapeData['features']))) { // eslint-disable-next-line @typescript-eslint/no-explicit-any const featureData: any[] = (!isNullOrUndefined(layer.shapeData['geometries']) && // eslint-disable-next-line @typescript-eslint/no-explicit-any (<any[]>layer.shapeData['geometries']).length > 0 ? layer.shapeData['geometries'] : layer.shapeData['features']); layer.layerData = []; // eslint-disable-next-line @typescript-eslint/no-explicit-any const bbox: any = layer.shapeData['bbox']; if (!isNullOrUndefined(bbox) && layer.isBaseLayer) { this.mapObject.baseMapBounds = new GeoLocation( { min: bbox[0][1], max: bbox[1][1] }, { min: bbox[0][0], max: bbox[1][0] } ); } else if (isNullOrUndefined(this.mapObject.baseMapBounds) && !isCustomPath(featureData)) { this.calculateRectBounds(featureData); } this.calculatePathCollection(layerIndex, featureData); } } } }); if (!this.mapObject.isTileMap) { this.mapObject.svgObject.appendChild(this.layerGroup); } else if (this.tileSvgObject) { this.tileSvgObject.appendChild(this.layerGroup); this.mapObject.baseMapBounds = null; } } private bingMapCalculation(layer: LayerSettings, layerIndex: number, proxy: LayerPanel, bing: BingMap): void { bing.imageUrl = layer.urlTemplate; bing.subDomains = ['t0', 't1', 't2', 't3']; bing.maxZoom = '21'; proxy.mapObject.bingMap = bing; proxy.renderTileLayer(proxy, layer, layerIndex, bing); this.mapObject.arrangeTemplate(); if (this.mapObject.zoomModule && (this.mapObject.previousScale !== this.mapObject.scale)) { this.mapObject.zoomModule.applyTransform(this.mapObject, false, true); } } private bubbleCalculation(bubbleSettings: BubbleSettingsModel, range: { min: number, max: number }): void { if (bubbleSettings.dataSource != null && bubbleSettings != null) { // eslint-disable-next-line @typescript-eslint/no-explicit-any const bubbleDataSource: any[] = bubbleSettings.dataSource as any[]; for (let i: number = 0; i < bubbleDataSource.length; i++) { const bubbledata: number = (!isNullOrUndefined(bubbleSettings.valuePath)) ? ((bubbleSettings.valuePath.indexOf('.') > -1) ? Number(getValueFromObject(bubbleSettings.dataSource[i as number], bubbleSettings.valuePath)) : parseFloat(bubbleSettings.dataSource[i as number][bubbleSettings.valuePath])) : parseFloat(bubbleSettings.dataSource[i as number][bubbleSettings.valuePath]); if (!isNaN(bubbledata)) { if (i !== 0) { if (bubbledata > range.max) { range.max = bubbledata; } else if (bubbledata < range.min) { range.min = bubbledata; } } else { range.max = range.min = bubbledata; } } } } } // eslint-disable-next-line @typescript-eslint/no-explicit-any public calculatePathCollection(layerIndex: number, renderData: any[]): void { this.groupElements = []; if ((!isCustomPath(renderData))) { this.currentFactor = this.calculateFactor(this.currentLayer); } this.rectBounds = null; const shapeSettings: ShapeSettings = <ShapeSettings>this.currentLayer.shapeSettings; for (let r: number = 0; r < renderData.length; r++) { // eslint-disable-next-line @typescript-eslint/no-explicit-any const geometryData: any = renderData[r as number]; // eslint-disable-next-line @typescript-eslint/no-explicit-any const geom: any = geometryData['geometry']; const hasGeom: boolean = !isNullOrUndefined(geom); const hasCoords: boolean = !isNullOrUndefined(geometryData['coordinates']); if (hasGeom || hasCoords) { const type: string = hasGeom ? geom['type'] : geometryData['type']; // eslint-disable-next-line @typescript-eslint/no-explicit-any const coords: any[] = hasGeom ? geom['coordinates'] : geometryData['coordinates']; // eslint-disable-next-line @typescript-eslint/no-explicit-any const data: any = geom; // eslint-disable-next-line @typescript-eslint/no-explicit-any const properties: any = geometryData['properties']; this.generatePoints(type, coords, data, properties); } } this.currentLayer.rectBounds = this.rectBounds; if (isNullOrUndefined(this.mapObject.baseMapRectBounds) && this.currentLayer.isBaseLayer) { this.mapObject.baseMapRectBounds = this.rectBounds; } const colors: string[] = (!isNullOrUndefined(shapeSettings.palette) && shapeSettings.palette.length > 1) ? shapeSettings.palette : getShapeColor(this.mapObject.theme); const areaRect: Rect = this.mapObject.mapAreaRect; const labelTemplateEle: HTMLElement = createElement('div', { id: this.mapObject.element.id + '_LayerIndex_' + layerIndex + '_Label_Template_Group', className: this.mapObject.element.id + '_template' }); labelTemplateEle.style.cssText = 'pointer-events: none; overflow: hidden; position: absolute;' + 'top:' + areaRect.y + 'px;' + 'left:' + areaRect.x + 'px;' + 'height:' + areaRect.height + 'px;' + 'width:' + areaRect.width + 'px;'; if (this.currentLayer.layerData.length !== 0) { for (let i: number = 0; i < this.currentLayer.layerData.length; i++) { let k: number; const borderValue: BorderModel = { color: shapeSettings.border.color || this.mapObject.themeStyle.shapeBorderColor, width: shapeSettings.border.width, opacity: shapeSettings.border.opacity }; // eslint-disable-next-line @typescript-eslint/no-explicit-any const currentShapeData: any[] = <any[]>this.currentLayer.layerData[i as number]; let pathOptions: PathOption; let circleOptions: CircleOption; let groupElement: Element; let path: string = ''; let fill: string = (shapeSettings.autofill) ? colors[i % colors.length] : (shapeSettings.fill || this.mapObject.themeStyle.shapeFill); if (shapeSettings.colorValuePath !== null && !isNullOrUndefined(currentShapeData['property'])) { k = checkShapeDataFields( // eslint-disable-next-line @typescript-eslint/no-explicit-any <any[]>this.currentLayer.dataSource, currentShapeData['property'], this.currentLayer.shapeDataPath, this.currentLayer.shapePropertyPath, this.currentLayer ); if (k !== null && shapeSettings.colorMapping.length === 0) { fill = ((this.currentLayer.shapeSettings.colorValuePath.indexOf('.') > -1) ? (getValueFromObject(this.currentLayer.dataSource[k as number], shapeSettings.colorValuePath)) : this.currentLayer.dataSource[k as number][shapeSettings.colorValuePath]); } else if (currentShapeData['property'][shapeSettings.colorValuePath] && // eslint-disable-next-line @typescript-eslint/no-explicit-any (<any[]>this.currentLayer.dataSource).length === 0 && shapeSettings.colorMapping.length === 0) { fill = ((this.currentLayer.shapeSettings.colorValuePath.indexOf('.') > -1) ? (getValueFromObject(currentShapeData['property'], shapeSettings.colorValuePath)) : currentShapeData['property'][shapeSettings.colorValuePath]); } fill = !isNullOrUndefined(fill) ? fill : (shapeSettings.fill || this.mapObject.themeStyle.shapeFill); } const shapeID: string = this.mapObject.element.id + '_LayerIndex_' + layerIndex + '_shapeIndex_' + i + '_dataIndex_' + k; // eslint-disable-next-line @typescript-eslint/no-explicit-any const getShapeColor: any = this.getShapeColorMapping(this.currentLayer, currentShapeData['property'], fill); fill = Object.prototype.toString.call(getShapeColor) === '[object Object]' && !isNullOrUndefined(getShapeColor['fill']) ? getShapeColor['fill'] : fill; if (this.currentLayer.shapeSettings.borderColorValuePath || this.currentLayer.shapeSettings.borderWidthValuePath) { k = checkShapeDataFields( // eslint-disable-next-line @typescript-eslint/no-explicit-any <any[]>this.currentLayer.dataSource, currentShapeData['property'], this.currentLayer.shapeDataPath, this.currentLayer.shapePropertyPath, this.currentLayer ); if (k !== null) { // eslint-disable-next-line @typescript-eslint/no-explicit-any const currentDataSource: any = this.currentLayer.dataSource[k as number]; if (currentDataSource[shapeSettings.borderColorValuePath]) { borderValue.color = currentDataSource[shapeSettings.borderColorValuePath]; } if (currentDataSource[shapeSettings.borderWidthValuePath]) { borderValue.width = currentDataSource[shapeSettings.borderWidthValuePath]; } } } const opacity: number = (Object.prototype.toString.call(getShapeColor) === '[object Object]' && !isNullOrUndefined(getShapeColor['opacity'])) ? getShapeColor['opacity'] : shapeSettings.opacity; const eventArgs: IShapeRenderingEventArgs = { cancel: false, name: shapeRendering, index: i, data: this.currentLayer.dataSource ? this.currentLayer.dataSource[k as number] : null, maps: this.mapObject, shape: shapeSettings, fill: fill, border: { width: borderValue.width, color: borderValue.color, opacity: borderValue.opacity} }; // eslint-disable-next-line @typescript-eslint/no-explicit-any const shapeRenderingSuccess: any = (eventArgs: IShapeRenderingEventArgs) => { let drawingType: string = !isNullOrUndefined(currentShapeData['_isMultiPolygon']) ? 'MultiPolygon' : isNullOrUndefined(currentShapeData['type']) ? currentShapeData[0]['type'] : currentShapeData['type']; drawingType = (drawingType === 'Polygon' || drawingType === 'MultiPolygon') ? 'Polygon' : drawingType; if (!eventArgs.cancel) { eventArgs.fill = eventArgs.fill === '#A6A6A6' ? eventArgs.shape.fill || this.mapObject.themeStyle.shapeFill : eventArgs.fill; eventArgs.border.color = eventArgs.border.color === 'transparent' ? eventArgs.shape.border.color : eventArgs.border.color; eventArgs.border.width = eventArgs.border.width === 0 ? eventArgs.shape.border.width : eventArgs.border.width; if (isNullOrUndefined(shapeSettings.borderColorValuePath)) { borderValue.color = eventArgs.border.color; } if (isNullOrUndefined(shapeSettings.borderWidthValuePath)) { borderValue.width = eventArgs.border.width; } } else { eventArgs.fill = fill; eventArgs.border.color = shapeSettings.border.color || this.mapObject.themeStyle.shapeBorderColor; eventArgs.border.width = shapeSettings.border.width; } eventArgs.border.opacity = isNullOrUndefined(eventArgs.border.opacity) ? opacity : eventArgs.border.opacity; if (this.groupElements.length < 1) { groupElement = this.mapObject.renderer.createGroup({ id: this.mapObject.element.id + '_LayerIndex_' + layerIndex + '_' + drawingType + '_Group', transform: '' }); this.groupElements.push(groupElement); } else { for (let i: number = 0; i < this.groupElements.length; i++) { const ele: Element = this.groupElements[i as number]; if (ele.id.indexOf(drawingType) > -1) { groupElement = ele; break; } else if (i >= this.groupElements.length - 1) { groupElement = this.mapObject.renderer.createGroup({ id: this.mapObject.element.id + '_LayerIndex_' + layerIndex + '_' + drawingType + '_Group' }); this.groupElements.push(groupElement); break; } } } let pathEle: Element; switch (drawingType) { case 'Polygon': if (!currentShapeData['_isMultiPolygon']) { // eslint-disable-next-line @typescript-eslint/no-explicit-any const shapeData: any[] = currentShapeData as any[]; if (shapeData.length > 0) { // eslint-disable-next-line @typescript-eslint/no-explicit-any const firstPoint: any = shapeData[0]['point']; const pathSegments: string[] = ['M', String(firstPoint['x']), String(firstPoint['y'])]; for (let index: number = 0; index < shapeData.length; index++) { // eslint-disable-next-line @typescript-eslint/no-explicit-any const point: any = shapeData[index as number]['point']; pathSegments.push('L', String(point['x']), String(point['y'])); } pathSegments.push('z'); path = pathSegments.join(' '); } } else { // eslint-disable-next-line @typescript-eslint/no-explicit-any path = this.generateMultiPolygonPath(<any[]>currentShapeData); path += ' z '; } if (path.length > 3) { pathOptions = new PathOption( shapeID, eventArgs.fill, eventArgs.border.width, eventArgs.border.color, opacity, eventArgs.border.opacity, shapeSettings.dashArray, path); pathEle = this.mapObject.renderer.drawPath(pathOptions) as SVGPathElement; } break; case 'LineString': // eslint-disable-next-line @typescript-eslint/no-explicit-any currentShapeData.map((lineData: any, index: number) => { if (index === 0) { path += 'M ' + (lineData['point']['x']) + ' ' + (lineData['point']['y']); } else { path += 'L' + (lineData['point']['x']) + ' , ' + (lineData['point']['y']) + ' '; } }); if (path.length > 3) { pathOptions = new PathOption( shapeID, 'transparent', !isNullOrUndefined(eventArgs.border.width) ? eventArgs.border.width : 1, !isNullOrUndefined(eventArgs.fill) ? eventArgs.fill : eventArgs.border.color, opacity, eventArgs.border.opacity, shapeSettings.dashArray, path); pathEle = this.mapObject.renderer.drawPath(pathOptions) as SVGPathElement; } break; case 'MultiLineString': // eslint-disable-next-line @typescript-eslint/no-explicit-any currentShapeData.map((multilineData: any) => { // eslint-disable-next-line @typescript-eslint/no-explicit-any multilineData.map((lineData: any, index: number) => { if (index === 0) { path += 'M ' + (lineData['point']['x']) + ' ' + (lineData['point']['y']); } else { path += 'L' + (lineData['point']['x']) + ' , ' + (lineData['point']['y']) + ' '; } }); }); if (path.length > 3) { pathOptions = new PathOption( shapeID, 'transparent', !isNullOrUndefined(eventArgs.border.width) ? eventArgs.border.width : 1, !isNullOrUndefined(eventArgs.fill) ? eventArgs.fill : eventArgs.border.color, opacity, eventArgs.border.opacity, shapeSettings.dashArray, path); pathEle = this.mapObject.renderer.drawPath(pathOptions) as SVGPathElement; } break; case 'Point': // eslint-disable-next-line @typescript-eslint/no-explicit-any const pointData: any = <any>currentShapeData['point']; const circleRadius: number = (this.mapObject.layers[layerIndex as number].type !== 'SubLayer') ? shapeSettings.circleRadius : shapeSettings.circleRadius / (this.mapObject.isTileMap ? this.mapObject.scale : this.currentFactor); circleOptions = new CircleOption( shapeID, eventArgs.fill, eventArgs.border, opacity, pointData['x'], pointData['y'], circleRadius, shapeSettings.dashArray); pathEle = this.mapObject.renderer.drawCircle(circleOptions) as SVGCircleElement; break; case 'MultiPoint': // eslint-disable-next-line @typescript-eslint/no-explicit-any currentShapeData.map((multiPointData: any, index: number) => { // eslint-disable-next-line @typescript-eslint/no-explicit-any const pointData: any = multiPointData['point']; const circleRadius: number = (this.mapObject.layers[layerIndex as number].type !== 'SubLayer') ? shapeSettings.circleRadius : shapeSettings.circleRadius / (this.mapObject.isTileMap ? this.mapObject.scale : this.currentFactor); circleOptions = new CircleOption( (shapeID + '_multiLine_' + index), eventArgs.fill, eventArgs.border, opacity, pointData['x'], pointData['y'], circleRadius, shapeSettings.dashArray); pathEle = this.mapObject.renderer.drawCircle(circleOptions) as SVGCircleElement; this.pathAttributeCalculate(groupElement, pathEle, drawingType, currentShapeData); }); break; case 'Path': path = <string>currentShapeData['point']; pathOptions = new PathOption( shapeID, eventArgs.fill, eventArgs.border.width, eventArgs.border.color, opacity, eventArgs.border.opacity, shapeSettings.dashArray, path); pathEle = this.mapObject.renderer.drawPath(pathOptions) as SVGPathElement; break; } if (!isNullOrUndefined(pathEle) && drawingType !== 'MultiPoint') { this.pathAttributeCalculate(groupElement, pathEle, drawingType, currentShapeData); } if (i === this.currentLayer.layerData.length - 1) { this.layerFeatures(layerIndex, colors, renderData, labelTemplateEle); } }; shapeRenderingSuccess.bind(this); this.mapObject.trigger('shapeRendering', eventArgs, shapeRenderingSuccess); } } else { this.layerFeatures(layerIndex, colors, renderData, labelTemplateEle); } } /** * layer features as bubble, marker, datalabel, navigation line. * * @param {Element} groupElement - Specifies the element to append the group. * @param {Element} pathEle - Specifies the svg element. * @param {string} drawingType - Specifies the data type. * @param {any} currentShapeData - Specifies the layer of shapedata. * @returns {void} */ private pathAttributeCalculate(groupElement: Element, pathEle: Element, drawingType: string, // eslint-disable-next-line @typescript-eslint/no-explicit-any currentShapeData: any): void { const property: string[] = (Object.prototype.toString.call(this.currentLayer.shapePropertyPath) === '[object Array]' ? this.currentLayer.shapePropertyPath : [this.currentLayer.shapePropertyPath]) as string[]; let properties: string; for (let j: number = 0; j < property.length; j++) { if (!isNullOrUndefined(currentShapeData['property'])) { properties = property[j as number]; break; } } pathEle.setAttribute('aria-label', ((!isNullOrUndefined(currentShapeData['property'])) ? (currentShapeData['property'][properties as string]) : '')); if (this.currentLayer.selectionSettings.enable || this.currentLayer.highlightSettings.enable) { (pathEle as HTMLElement).tabIndex = this.mapObject.tabIndex; pathEle.setAttribute('role', 'button'); (pathEle as HTMLElement).style.cursor = this.currentLayer.highlightSettings.enable && !this.currentLayer.selectionSettings.enable ? 'default' : 'pointer'; } else { pathEle.setAttribute('role', 'region'); } if (drawingType === 'LineString' || drawingType === 'MultiLineString') { (pathEle as HTMLElement).style.cssText = 'outline:none'; } maintainSelection(this.mapObject.selectedElementId, this.mapObject.shapeSelectionClass, pathEle, 'ShapeselectionMapStyle'); if (this.mapObject.legendSettings.toggleLegendSettings.enable && this.mapObject.legendSettings.type === 'Layers') { maintainToggleSelection(this.mapObject.toggledElementId, pathEle, this.mapObject.legendSettings.toggleLegendSettings.applyShapeSettings ? this.currentLayer.shapeSettings : this.mapObject.legendSettings.toggleLegendSettings); } groupElement.appendChild(pathEle); } /** * layer features as bubble, marker, datalabel, navigation line. * * @param {number} layerIndex - Specifies the layer index * @param {string[]} colors - Specifies the colors * @param {any[]} renderData - Specifies the render data * @param {HTMLElement} labelTemplateEle - Specifies the label template element * @returns {void} */ private layerFeatures( // eslint-disable-next-line @typescript-eslint/no-explicit-any layerIndex: number, colors: string[], renderData: any[], labelTemplateEle: HTMLElement ): void { let bubbleG: Element; if (this.mapObject.polygonModule) { this.groupElements.push( this.mapObject.polygonModule.polygonRender(this.mapObject, layerIndex, (this.mapObject.isTileMap ? Math.floor(this.currentFactor) : this.currentFactor))); } if (this.currentLayer.bubbleSettings.length && this.mapObject.bubbleModule) { const length: number = this.currentLayer.bubbleSettings.length; let bubble: BubbleSettingsModel; for (let j: number = 0; j < length; j++) { bubble = this.currentLayer.bubbleSettings[j as number]; bubbleG = this.mapObject.renderer.createGroup({ id: this.mapObject.element.id + '_LayerIndex_' + layerIndex + '_bubble_Group_' + j }); const range: { min: number; max: number; } = { min: 0, max: 0 }; this.bubbleCalculation(bubble, range); // eslint-disable-next-line @typescript-eslint/no-explicit-any const bubbleDataSource: any[] = bubble.dataSource as any[]; this.mapObject.bubbleModule.bubbleCollection = []; if (!isNullOrUndefined(bubbleDataSource) && bubbleDataSource.length > 0) { bubbleDataSource.map((bubbleData: object, i: number) => { this.renderBubble( this.currentLayer, bubbleData, colors[i % colors.length], range, j, i, bubbleG, layerIndex, bubble); }); this.groupElements.push(bubbleG); } } } if ((this.mapObject.markerModule && !this.mapObject.isTileMap) && this.mapObject.zoomSettings.enable) { this.mapObject.markerModule.calculateZoomCenterPositionAndFactor(this.mapObject.layersCollection); } const group: Element = (this.mapObject.renderer.createGroup({ id: this.mapObject.element.id + '_LayerIndex_' + layerIndex + '_dataLableIndex_Group' })); (group as HTMLElement).style.pointerEvents = 'none'; if (this.mapObject.dataLabelModule && this.currentLayer.dataLabelSettings.visible) { // eslint-disable-next-line @typescript-eslint/no-explicit-any const intersect: any[] = []; // eslint-disable-next-line @typescript-eslint/no-explicit-any Array.prototype.forEach.call(renderData, (currentShapeData: any[], i: number) => { this.renderLabel(this.currentLayer, layerIndex, currentShapeData, group, i, labelTemplateEle, intersect); }); this.groupElements.push(group); } if (this.mapObject.navigationLineModule) { this.groupElements.push( this.mapObject.navigationLineModule.renderNavigation(this.currentLayer, this.currentFactor, layerIndex) ); } if (!isNullOrUndefined(this.groupElements) && !isNullOrUndefined(this.layerObject)) { this.groupElements.map((element: Element) => { if (!isNullOrUndefined(element)) { this.layerObject.appendChild(element); } }); } if (this.mapObject.markerModule) { this.mapObject.markerModule.markerRender(this.mapObject, this.layerObject, layerIndex, (this.mapObject.isTileMap ? Math.floor(this.currentFactor) : this.currentFactor), null); } this.translateLayerElements(this.layerObject); this.layerGroup.appendChild(this.layerObject); } /** * render datalabel. * * @param {LayerSettings} layer - Specifies the layer * @param {number} layerIndex - Specifies the layer index * @param {any[]} shape - Specifies the shape * @param {Element} group - Specifies the group * @param {number} shapeIndex - Specifies the shape index * @param {HTMLElement} labelTemplateEle - Specifies the label template element * @param {any[]} intersect - Specifies the intersect * @returns {void} */ private renderLabel( layer: LayerSettings, layerIndex: number, // eslint-disable-next-line @typescript-eslint/no-explicit-any shape: any[], group: Element, shapeIndex: number, labelTemplateEle: HTMLElement, intersect: any[] ): void { this.mapObject.dataLabelModule.renderLabel( layer, layerIndex, shape, layer.layerData, group, labelTemplateEle, shapeIndex, intersect ); } /** * To render path for multipolygon. * * @param {any[]} currentShapeData Specifies the current shape data * @returns {string} Returns the path */ // eslint-disable-next-line @typescript-eslint/no-explicit-any private generateMultiPolygonPath(currentShapeData: any[]): string { const parts: string[] = []; for (const shape of currentShapeData) { if (!shape || shape.length === 0) { continue; } const startX: number = shape[0].point.x; const startY: number = shape[0].point.y; parts.push(`M${startX} ${startY}`); for (let i: number = 1; i < shape.length; i++) { const x: number = shape[i as number].point.x; const y: number = shape[i as number].point.y; parts.push(` L ${x} ${y}`); } } return parts.join(' '); } /** * To render bubble. * * @param {LayerSettings} layer - Specifies the layer * @param {object} bubbleData - Specifies the bubble data * @param {string} color - Specifies the color * @param {number} range - Specifies the range * @param {number} range.min - Specifies the minimum range * @param {number} range.max - Specifies the maximum range * @param {number} bubbleIndex - Specifies the bubble index * @param {number} dataIndex - Specifies the data index * @param {number} group - Specifies the group * @param {number} layerIndex - Specifies the layer index * @param {BubbleSettingsModel} bubbleSettings - Specifies the bubble settings * @returns {void} */ private renderBubble( // eslint-disable-next-line @typescript-eslint/no-explicit-any layer: LayerSettings, bubbleData: any, color: string, range: { min: number, max: number }, bubbleIndex: number, dataIndex: number, group: Element, layerIndex: number, bubbleSettings: BubbleSettingsModel ): void { if (isNullOrUndefined(this.mapObject.bubbleModule) || !bubbleSettings.visible) { return null; } color = bubbleSettings.fill ? bubbleSettings.fill : color; this.mapObject.bubbleModule.id = this.mapObject.element.id + '_LayerIndex_' + layerIndex + '_BubbleIndex_' + bubbleIndex + '_dataIndex_' + dataIndex; this.mapObject.bubbleModule.renderBubble( bubbleSettings, bubbleData, color, range, bubbleIndex, dataIndex, layerIndex, layer, group, this.mapObject.bubbleModule.id); } /** * To get the shape color from color mapping module. * * @param {LayerSettingsModel} layer - Specifies the layer * @param {any} shape - Specifies the shape * @param {string} color - Specifies the color * @returns {any} - Returns the object */ // eslint-disable-next-line @typescript-eslint/no-explicit-any private getShapeColorMapping(layer: LayerSettingsModel, shape: any, color: string): any { color = color ? color : layer.shapeSettings.fill; if (layer.shapeSettings.colorMapping.length === 0 && isNullOrUndefined(layer.dataSource)) { return color; } // eslint-disable-next-line @typescript-eslint/no-explicit-any const index: number = checkShapeDataFields(<any[]>layer.dataSource, shape, layer.shapeDataPath, layer.shapePropertyPath, layer); const colorMapping