import { Injectable, Renderer2, RendererFactory2 } from '@angular/core'; import { BehaviorSubject, Observable } from 'rxjs'; // Helpers import { MapMarkerIconHelper } from '../helpers'; // Constants import { MapMarkerIconsConstants } from '../constants'; // Models import { IMapMarkers } from '../../models'; // Enums import { eGpsMotionStatus } from '../../../../enums'; @Injectable({ providedIn: 'root', }) export class MapMarkerIconService { private renderer: Renderer2; private clusterMarkerIds = new BehaviorSubject([]); public clusterMarkerIds$: Observable = this.clusterMarkerIds.asObservable(); private routingMarkerIds = new BehaviorSubject([]); public routingMarkerIds$: Observable = this.routingMarkerIds.asObservable(); private markerElements = new BehaviorSubject([]); private clusterElements = new BehaviorSubject([]); private routingElements = new BehaviorSubject([]); constructor(rendererFactory: RendererFactory2) { this.renderer = rendererFactory.createRenderer(null, null); } public getMarkerIcon( markerId: number, labelName?: string, isClosed?: boolean, isFavorite?: boolean, isAlwaysSelected?: boolean, fuelMarkerClass?: string, secondLabelName?: string, isCreateNewMarker?: boolean ): HTMLElement { const markerElements = this.markerElements.getValue(); const previousMarkerIcon = markerElements.find( (icon) => icon.id === 'marker-' + markerId ); if (previousMarkerIcon && !isCreateNewMarker) return previousMarkerIcon; else { const markerElement = this.renderer.createElement('div'); this.renderer.setAttribute( markerElement, 'id', 'marker-' + markerId ); this.renderer.addClass(markerElement, 'marker-icon'); const markerSvg = isClosed ? MapMarkerIconsConstants.closedMarker : isFavorite ? MapMarkerIconsConstants.favoriteMarker : MapMarkerIconsConstants.defaultMarker; this.renderer.setProperty(markerElement, 'innerHTML', markerSvg); if (labelName) { const markerLabelElement = this.renderer.createElement('div'); this.renderer.addClass(markerLabelElement, 'marker-label'); const markerLabelText = this.renderer.createElement('div'); this.renderer.addClass(markerLabelText, 'marker-label-text'); const labelText = isAlwaysSelected ? labelName : labelName.toUpperCase(); this.renderer.setProperty( markerLabelText, 'innerHTML', labelText ); this.renderer.appendChild(markerLabelElement, markerLabelText); if (secondLabelName) { const secondLabelElement = this.renderer.createElement('div'); this.renderer.addClass( secondLabelElement, 'marker-label-second-text' ); this.renderer.addClass(secondLabelElement, 'ca-font-bold'); this.renderer.addClass(secondLabelElement, 'line-clamp-1'); this.renderer.setProperty( secondLabelElement, 'innerHTML', secondLabelName.toUpperCase() ); this.renderer.appendChild( markerLabelElement, secondLabelElement ); this.renderer.addClass(markerLabelText, 'line-clamp-1'); } this.renderer.appendChild(markerElement, markerLabelElement); } if (isAlwaysSelected) this.renderer.addClass(markerElement, 'selected-permanently'); if (fuelMarkerClass && !isClosed) { this.renderer.addClass(markerElement, 'fuel-icon'); this.renderer.addClass(markerElement, fuelMarkerClass); } markerElements.push(markerElement); this.markerElements.next(markerElements); return markerElement; } } public getClusterMarkerIcon( markerData: IMapMarkers, isFuelMarker?: boolean ): HTMLElement { const clusterElements = this.clusterElements.getValue(); const clusterId = this.createClusterId(markerData); const previousClusterIcon = clusterElements.find( (icon) => icon.id === 'cluster-' + clusterId ); if (previousClusterIcon) return previousClusterIcon; else { const markerElement = this.renderer.createElement('div'); this.renderer.setAttribute( markerElement, 'id', 'cluster-' + clusterId ); this.renderer.addClass(markerElement, 'cluster-icon'); if (isFuelMarker) this.renderer.addClass(markerElement, 'fuel-icon'); const markerSvg = MapMarkerIconHelper.getClusterMarker( markerData.data.count, false, isFuelMarker ); this.renderer.setProperty(markerElement, 'innerHTML', markerSvg); clusterElements.push(markerElement); this.clusterElements.next(clusterElements); return markerElement; } } public getRoutingMarkerIcon( markerData: IMapMarkers, stopNumber: number, stopType: string, isStopChecked?: boolean, isLightMode?: boolean, labelName?: string ): HTMLElement { const routingElements = this.routingElements.getValue(); const routingId = markerData.id ?? this.createRoutingId(markerData); const previousClusterIcon = routingElements.find( (icon) => icon.id === 'routingMarker-' + routingId ); if (previousClusterIcon) return previousClusterIcon; else { const markerElement = this.renderer.createElement('div'); this.renderer.setAttribute( markerElement, 'id', 'routingMarker-' + routingId ); this.renderer.addClass(markerElement, 'routing-icon'); const markerSvg = MapMarkerIconHelper.getRoutingMarkerIcon( stopNumber, stopType, isStopChecked, isLightMode ); this.renderer.setProperty(markerElement, 'innerHTML', markerSvg); if (labelName) { const markerLabelElement = this.renderer.createElement('div'); this.renderer.addClass(markerLabelElement, 'marker-label'); this.renderer.setProperty( markerLabelElement, 'innerHTML', labelName.toUpperCase() ); this.renderer.appendChild(markerElement, markerLabelElement); } routingElements.push(markerElement); this.routingElements.next(routingElements); return markerElement; } } public getCurrentLocationMarkerIcon( markerData: IMapMarkers, motionStatus: eGpsMotionStatus ): HTMLElement { const routingElements = this.routingElements.getValue(); const routingId = markerData.id ?? this.createRoutingId(markerData); const previousClusterIcon = routingElements.find( (icon) => icon.id === 'routingMarker-' + routingId ); if (previousClusterIcon) return previousClusterIcon; else { const markerElement = this.renderer.createElement('div'); this.renderer.setAttribute( markerElement, 'id', 'routingMarker-' + routingId ); this.renderer.addClass(markerElement, 'routing-icon'); this.renderer.addClass(markerElement, 'd-flex'); const markerSvg = MapMarkerIconHelper.getCurrentLocationMarkerSvg(motionStatus); this.renderer.setProperty(markerElement, 'innerHTML', markerSvg); routingElements.push(markerElement); this.routingElements.next(routingElements); return markerElement; } } public createClusterId(clusterData: IMapMarkers): number { const clusterMarkers = this.clusterMarkerIds.getValue(); const clusterId = clusterMarkers.find( (item) => clusterData?.id === item?.id )?.id; if (clusterId) return clusterId; else { const newId = crypto.getRandomValues(new Uint32Array(1))[0]; const newData = { ...clusterData, id: newId, }; clusterMarkers.push(newData); this.clusterMarkerIds.next(clusterMarkers); return newId; } } public createRoutingId(markerData: IMapMarkers): number { const routingMarkers = this.routingMarkerIds.getValue(); const routingId = routingMarkers.find( (item) => markerData?.id === item?.id )?.id; if (routingId) return routingId; else { const newId = markerData?.id ?? crypto.getRandomValues(new Uint32Array(1))[0]; const newData = { ...markerData, id: newId, }; routingMarkers.push(newData); this.routingMarkerIds.next(routingMarkers); return newId; } } public resetMarkersData(): void { this.clusterMarkerIds.next([]); this.routingMarkerIds.next([]); this.markerElements.next([]); this.clusterElements.next([]); this.routingElements.next([]); } }