diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/markers-data-layer.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/markers-data-layer.ts index f835c0578b..b5dbedf90f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/markers-data-layer.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/markers-data-layer.ts @@ -73,8 +73,7 @@ export class MarkerDataProcessor { @@ -171,7 +170,7 @@ export class MarkerDataProcessor { return createColorMarkerIconElement(this.dataLayer.getCtx().$injector.get(MatIconRegistry), this.dataLayer.getCtx().$injector.get(DomSanitizer), - iconContainer, icon, color, this.trip).pipe( + iconContainer, icon, color).pipe( map((element) => { if (rotationAngle !== 0) { element.style.transform = `rotate(${rotationAngle}deg)`; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/trips-data-layer.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/trips-data-layer.ts index 72400b0f38..9e0a5fe4bf 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/trips-data-layer.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/trips-data-layer.ts @@ -553,7 +553,7 @@ export class TbTripsDataLayer extends TbMapDataLayer[] = [this.dataProcessor.setup()]; if (this.settings.showPath) { this.pathStrokeColorProcessor = new DataLayerColorProcessor(this, this.settings.pathStrokeColor); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map.ts index c88d8072e3..66475705f7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map.ts @@ -171,6 +171,7 @@ export abstract class TbMap { } private setupControls(): Observable { + //L.control.scale().addTo(this.map); if (this.map.zoomControl) { this.map.zoomControl.setPosition(this.settings.controlsPosition); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-icon-shapes.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-icon-shapes.component.ts index b4cfa7ae00..3240ce11dd 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-icon-shapes.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-icon-shapes.component.ts @@ -115,7 +115,7 @@ export class MarkerIconShapesComponent extends PageComponent implements OnInit { this.iconContainers = containersList.map((iconContainer) => { return { iconContainer, - html$: createColorMarkerIconElement(this.iconRegistry, this.domSanitizer, iconContainer, this.icon, tinycolor(this.color), this.trip).pipe( + html$: createColorMarkerIconElement(this.iconRegistry, this.domSanitizer, iconContainer, this.icon, tinycolor(this.color)).pipe( map((element) => { return this.domSanitizer.bypassSecurityTrustHtml(element.outerHTML); }), diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-shape-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-shape-settings.component.ts index ef6a85ac8c..14e80e4fd2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-shape-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-shape-settings.component.ts @@ -208,7 +208,7 @@ export class MarkerShapeSettingsComponent implements ControlValueAccessor, OnIni } else if (this.markerType === MarkerType.icon) { const iconContainer = (this.modelValue as MarkerIconSettings).iconContainer; const icon = (this.modelValue as MarkerIconSettings).icon; - this.iconPreview$ = createColorMarkerIconElement(this.iconRegistry, this.domSanitizer, iconContainer, icon, tinycolor(color), this.trip).pipe( + this.iconPreview$ = createColorMarkerIconElement(this.iconRegistry, this.domSanitizer, iconContainer, icon, tinycolor(color)).pipe( map((element) => { return this.domSanitizer.bypassSecurityTrustHtml(element.outerHTML); }), diff --git a/ui-ngx/src/app/shared/models/widget/maps/marker-shape.models.ts b/ui-ngx/src/app/shared/models/widget/maps/marker-shape.models.ts index 76a8af733f..3d8f44df3f 100644 --- a/ui-ngx/src/app/shared/models/widget/maps/marker-shape.models.ts +++ b/ui-ngx/src/app/shared/models/widget/maps/marker-shape.models.ts @@ -21,6 +21,7 @@ import { Observable, of, shareReplay, switchMap } from 'rxjs'; import { catchError, map, take } from 'rxjs/operators'; import { isSvgIcon, splitIconName } from '@shared/models/icon.models'; import { Element, G, SVG, Text } from '@svgdotjs/svg.js'; +import { guid } from '@core/utils'; export enum MarkerShape { markerShape1 = 'markerShape1', @@ -47,10 +48,14 @@ export enum MarkerShape { export enum MarkerIconContainer { iconContainer1 = 'iconContainer1', - tripIconContainer1 = 'tripIconContainer1' + iconContainer2 = 'iconContainer2', + iconContainer3 = 'iconContainer3', + tripIconContainer1 = 'tripIconContainer1', + tripIconContainer2 = 'tripIconContainer2', + tripIconContainer3 = 'tripIconContainer3' } -export const markerShapeMap = new Map( +const markerShapeMap = new Map( [ [MarkerShape.markerShape1, '/assets/markers/shape1.svg'], [MarkerShape.markerShape2, '/assets/markers/shape2.svg'], @@ -75,10 +80,69 @@ export const markerShapeMap = new Map( ] ); -export const markerIconContainerMap = new Map( +const markerIconContainerMap = new Map( [ [MarkerIconContainer.iconContainer1, '/assets/markers/iconContainer1.svg'], - [MarkerIconContainer.tripIconContainer1, '/assets/markers/tripIconContainer1.svg'] + [MarkerIconContainer.iconContainer2, '/assets/markers/iconContainer2.svg'], + [MarkerIconContainer.iconContainer3, '/assets/markers/iconContainer3.svg'], + [MarkerIconContainer.tripIconContainer1, '/assets/markers/tripIconContainer1.svg'], + [MarkerIconContainer.tripIconContainer2, '/assets/markers/tripIconContainer2.svg'], + [MarkerIconContainer.tripIconContainer3, '/assets/markers/tripIconContainer3.svg'] + ] +); + +interface MarkerIconContainerDefinition { + iconSize: number; + iconColor: (color: tinycolor.Instance) => tinycolor.Instance; + iconAlpha: (color: tinycolor.Instance) => number; + appendIcon?: (svgElement: SVGElement, iconElement: Element) => void; +} + +const emptyIconContainerDefinition: MarkerIconContainerDefinition = { + iconSize: 24, + iconColor: (color) => color, + iconAlpha: color => color.getAlpha() +} + +const defaultIconContainerDefinition: MarkerIconContainerDefinition = { + iconSize: 12, + iconColor: (color) => tinycolor.mix(color.clone().setAlpha(1), tinycolor('rgba(0,0,0,0.38)')), + iconAlpha: color => color.getAlpha() +} + +const defaultTripIconContainerDefinition: MarkerIconContainerDefinition = { + iconSize: 24, + iconColor: () => tinycolor('#000'), + iconAlpha: () => 1, + appendIcon: (svgElement, iconElement) => { + const box = iconElement.bbox(); + let elements = svgElement.getElementsByClassName('icon-mask-exclude'); + if (elements.length) { + elements = elements[0].getElementsByClassName('marker-icon-container'); + if (elements.length) { + const iconContainer = new G(elements[0] as SVGGElement); + iconContainer.add(iconElement.clone().fill('#000').translate(-box.cx, -box.cy)); + } + } + elements = svgElement.getElementsByClassName('icon-mask-overlay'); + if (elements.length) { + elements = elements[0].getElementsByClassName('marker-icon-container'); + if (elements.length) { + const iconContainer = new G(elements[0] as SVGGElement); + iconContainer.add(iconElement.clone().fill('#fff').translate(-box.cx, -box.cy)); + } + } + } +} + +const markerIconContainerDefinitionMap = new Map( + [ + [MarkerIconContainer.iconContainer1, defaultIconContainerDefinition], + [MarkerIconContainer.iconContainer2, defaultIconContainerDefinition], + [MarkerIconContainer.iconContainer3, defaultIconContainerDefinition], + [MarkerIconContainer.tripIconContainer1, defaultTripIconContainerDefinition], + [MarkerIconContainer.tripIconContainer2, {...defaultTripIconContainerDefinition, iconSize: 16}], + [MarkerIconContainer.tripIconContainer3, {...defaultTripIconContainerDefinition, iconSize: 16}] ] ); @@ -108,8 +172,45 @@ export const tripMarkerShapes = [ MarkerShape.tripMarkerShape10 ]; -export const markerIconContainers = [ MarkerIconContainer.iconContainer1 ]; -export const tripMarkerIconContainers = [ MarkerIconContainer.tripIconContainer1 ]; +export const markerIconContainers = [ + MarkerIconContainer.iconContainer1, + MarkerIconContainer.iconContainer2, + MarkerIconContainer.iconContainer3 +]; + +export const tripMarkerIconContainers = [ + MarkerIconContainer.tripIconContainer1, + MarkerIconContainer.tripIconContainer2, + MarkerIconContainer.tripIconContainer3 +]; + +const generateElementId = () => { + const id = guid(); + const firstChar = id.charAt(0); + if (firstChar >= '0' && firstChar <= '9') { + return 'a' + id; + } else { + return id; + } +}; + +const prepareSvgIds = (element: SVGElement): SVGElement => { + let svgContent = element.outerHTML; + const regexp = /\sid="([^"]*)"[\s>]/g; + const unique_id_suffix = '_' + generateElementId(); + const ids: string[] = []; + let match = regexp.exec(svgContent); + while (match !== null) { + ids.push(match[1]); + match = regexp.exec(svgContent); + } + for (const id of ids) { + const newId = id + unique_id_suffix; + svgContent = svgContent.replace(new RegExp('id="'+id+'"', 'g'), 'id="'+newId+'"'); + svgContent = svgContent.replace(new RegExp('url\\(#'+id+'\\)', 'g'), 'url(#'+newId+')'); + } + return SVG(svgContent).node; +}; const createColorMarkerShape = (iconRegistry: MatIconRegistry, domSanitizer: DomSanitizer, assetUrl: string, color: tinycolor.Instance): Observable => { const safeUrl = domSanitizer.bypassSecurityTrustResourceUrl(assetUrl); @@ -131,7 +232,14 @@ const createColorMarkerShape = (iconRegistry: MatIconRegistry, domSanitizer: Dom el.setAttribute('stroke', '#'+color.toHex()); el.setAttribute('stroke-opacity', `${color.getAlpha()}`); }); - return svgElement; + const opacityElements = Array.from(svgElement.getElementsByClassName('marker-opacity')); + if (svgElement.classList.contains('marker-opacity')) { + opacityElements.push(svgElement); + } + opacityElements.forEach(el => { + el.setAttribute('opacity', `${color.getAlpha()}`); + }); + return prepareSvgIds(svgElement); }) ); } @@ -147,10 +255,8 @@ export const createColorMarkerShapeURI = (iconRegistry: MatIconRegistry, domSani ); } -const createIconElement = (iconRegistry: MatIconRegistry, icon: string, size: number, color: tinycolor.Instance, trip = false): Observable => { +const createIconElement = (iconRegistry: MatIconRegistry, icon: string, size: number, iconColor: tinycolor.Instance, iconAlpha: number): Observable => { const isSvg = isSvgIcon(icon); - const iconAlpha = color.getAlpha(); - const iconColor = trip ? color : tinycolor.mix(color.clone().setAlpha(1), tinycolor('rgba(0,0,0,0.38)')); if (isSvg) { const [namespace, iconName] = splitIconName(icon); return iconRegistry @@ -190,24 +296,30 @@ const createIconElement = (iconRegistry: MatIconRegistry, icon: string, size: nu } export const createColorMarkerIconElement = (iconRegistry: MatIconRegistry, domSanitizer: DomSanitizer, - iconContainer: MarkerIconContainer, icon: string, color: tinycolor.Instance, - trip = false): Observable => { + iconContainer: MarkerIconContainer, icon: string, color: tinycolor.Instance): Observable => { const markerShape$: Observable = iconContainer ? createColorMarkerShape(iconRegistry, domSanitizer, markerIconContainerMap.get(iconContainer), color) : of(null); return markerShape$.pipe( switchMap((svgElement) => { - const iconSize = svgElement ? (trip ? 24 : 12) : 24; - const iconColor = svgElement ? (trip ? tinycolor('#fff') : color) : color; - return createIconElement(iconRegistry, icon, iconSize, iconColor, trip || !svgElement).pipe( + const definition = iconContainer ? markerIconContainerDefinitionMap.get(iconContainer) : emptyIconContainerDefinition; + const iconSize = definition.iconSize; + const iconColor = definition.iconColor(color); + const iconAlpha = definition.iconAlpha(color); + return createIconElement(iconRegistry, icon, iconSize, iconColor, iconAlpha).pipe( map((iconElement) => { if (svgElement) { - const elements = svgElement.getElementsByClassName('marker-icon-container'); - if (iconElement && elements.length) { - const iconContainer = new G(elements[0] as SVGGElement); - iconContainer.clear(); - iconContainer.add(iconElement); - const box = iconElement.bbox(); - iconElement.translate(-box.cx, -box.cy); + if (iconElement) { + if (definition.appendIcon) { + definition.appendIcon(svgElement, iconElement); + } else { + const elements = svgElement.getElementsByClassName('marker-icon-container'); + if (elements.length) { + const iconContainer = new G(elements[0] as SVGGElement); + iconContainer.add(iconElement); + const box = iconElement.bbox(); + iconElement.translate(-box.cx, -box.cy); + } + } } return svgElement; } else { diff --git a/ui-ngx/src/assets/markers/iconContainer1.svg b/ui-ngx/src/assets/markers/iconContainer1.svg index bf92e4d90f..d9e00d3934 100644 --- a/ui-ngx/src/assets/markers/iconContainer1.svg +++ b/ui-ngx/src/assets/markers/iconContainer1.svg @@ -1,22 +1,25 @@ - - + + - - - - - - + + + - + + + + diff --git a/ui-ngx/src/assets/markers/iconContainer2.svg b/ui-ngx/src/assets/markers/iconContainer2.svg new file mode 100644 index 0000000000..fa716aa30e --- /dev/null +++ b/ui-ngx/src/assets/markers/iconContainer2.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ui-ngx/src/assets/markers/iconContainer3.svg b/ui-ngx/src/assets/markers/iconContainer3.svg new file mode 100644 index 0000000000..a64995d1ee --- /dev/null +++ b/ui-ngx/src/assets/markers/iconContainer3.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + diff --git a/ui-ngx/src/assets/markers/shape1.svg b/ui-ngx/src/assets/markers/shape1.svg index 0a29bb7dbe..7399bab288 100644 --- a/ui-ngx/src/assets/markers/shape1.svg +++ b/ui-ngx/src/assets/markers/shape1.svg @@ -1,19 +1,22 @@ - - + + - - - - + - + - - - + + + + + + diff --git a/ui-ngx/src/assets/markers/shape10.svg b/ui-ngx/src/assets/markers/shape10.svg index f0d8b68d2f..d13fca2d2b 100644 --- a/ui-ngx/src/assets/markers/shape10.svg +++ b/ui-ngx/src/assets/markers/shape10.svg @@ -1,11 +1,11 @@ - - - + + + - + - + diff --git a/ui-ngx/src/assets/markers/shape2.svg b/ui-ngx/src/assets/markers/shape2.svg index 1c59215800..c60d909881 100644 --- a/ui-ngx/src/assets/markers/shape2.svg +++ b/ui-ngx/src/assets/markers/shape2.svg @@ -1,17 +1,23 @@ - - + + - - - + + + - + - - - + + + + + + diff --git a/ui-ngx/src/assets/markers/shape3.svg b/ui-ngx/src/assets/markers/shape3.svg index eb2fa563b7..e1f0a8ac1b 100644 --- a/ui-ngx/src/assets/markers/shape3.svg +++ b/ui-ngx/src/assets/markers/shape3.svg @@ -1,19 +1,22 @@ - - - + + + - - - - - + + - + - - - + + + + + + diff --git a/ui-ngx/src/assets/markers/shape4.svg b/ui-ngx/src/assets/markers/shape4.svg index 5303d47ba6..4190ce6d06 100644 --- a/ui-ngx/src/assets/markers/shape4.svg +++ b/ui-ngx/src/assets/markers/shape4.svg @@ -1,21 +1,24 @@ - - - + + + - - - - - - - + + + + - + - - - + + + + + + diff --git a/ui-ngx/src/assets/markers/shape5.svg b/ui-ngx/src/assets/markers/shape5.svg index db3c2e0118..e1080d7e19 100644 --- a/ui-ngx/src/assets/markers/shape5.svg +++ b/ui-ngx/src/assets/markers/shape5.svg @@ -1,20 +1,23 @@ - - - + + + - - - - - - + + + - + - - - + + + + + + diff --git a/ui-ngx/src/assets/markers/shape6.svg b/ui-ngx/src/assets/markers/shape6.svg index 19002cec71..b388f13bdf 100644 --- a/ui-ngx/src/assets/markers/shape6.svg +++ b/ui-ngx/src/assets/markers/shape6.svg @@ -1,19 +1,22 @@ - - + + - - - - + - + + + + diff --git a/ui-ngx/src/assets/markers/shape7.svg b/ui-ngx/src/assets/markers/shape7.svg index c7df181b78..aeef8c74c5 100644 --- a/ui-ngx/src/assets/markers/shape7.svg +++ b/ui-ngx/src/assets/markers/shape7.svg @@ -1,6 +1,6 @@ - - + + @@ -9,12 +9,12 @@ - + - - - + + + diff --git a/ui-ngx/src/assets/markers/shape8.svg b/ui-ngx/src/assets/markers/shape8.svg index 1fecf058d9..a303a36ba3 100644 --- a/ui-ngx/src/assets/markers/shape8.svg +++ b/ui-ngx/src/assets/markers/shape8.svg @@ -1,12 +1,12 @@ - - - - + + + + - + diff --git a/ui-ngx/src/assets/markers/shape9.svg b/ui-ngx/src/assets/markers/shape9.svg index f44a6b3626..52d1a03fa0 100644 --- a/ui-ngx/src/assets/markers/shape9.svg +++ b/ui-ngx/src/assets/markers/shape9.svg @@ -1,14 +1,14 @@ - - - + + + - - - + + + - + diff --git a/ui-ngx/src/assets/markers/tripIconContainer1.svg b/ui-ngx/src/assets/markers/tripIconContainer1.svg index df33957809..c1186b2aa9 100644 --- a/ui-ngx/src/assets/markers/tripIconContainer1.svg +++ b/ui-ngx/src/assets/markers/tripIconContainer1.svg @@ -1,12 +1,23 @@ - - - - + + + + + + + + + + + + + - - + + diff --git a/ui-ngx/src/assets/markers/tripIconContainer2.svg b/ui-ngx/src/assets/markers/tripIconContainer2.svg new file mode 100644 index 0000000000..229c98b31e --- /dev/null +++ b/ui-ngx/src/assets/markers/tripIconContainer2.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/ui-ngx/src/assets/markers/tripIconContainer3.svg b/ui-ngx/src/assets/markers/tripIconContainer3.svg new file mode 100644 index 0000000000..8a8baf2b1b --- /dev/null +++ b/ui-ngx/src/assets/markers/tripIconContainer3.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ui-ngx/src/assets/markers/tripShape10.svg b/ui-ngx/src/assets/markers/tripShape10.svg index 507d3725de..5fb5d81af1 100644 --- a/ui-ngx/src/assets/markers/tripShape10.svg +++ b/ui-ngx/src/assets/markers/tripShape10.svg @@ -1,10 +1,13 @@ - + - - + + diff --git a/ui-ngx/src/assets/markers/tripShape2.svg b/ui-ngx/src/assets/markers/tripShape2.svg index 0dfc4e22a1..e53beaf187 100644 --- a/ui-ngx/src/assets/markers/tripShape2.svg +++ b/ui-ngx/src/assets/markers/tripShape2.svg @@ -1,15 +1,29 @@ - - - - - + + + + + + + + + - + + + + + + + + + - - + + diff --git a/ui-ngx/src/assets/markers/tripShape3.svg b/ui-ngx/src/assets/markers/tripShape3.svg index e49d699ad2..ca81dc38e6 100644 --- a/ui-ngx/src/assets/markers/tripShape3.svg +++ b/ui-ngx/src/assets/markers/tripShape3.svg @@ -1,9 +1,12 @@ - + - - + + diff --git a/ui-ngx/src/assets/markers/tripShape4.svg b/ui-ngx/src/assets/markers/tripShape4.svg index f4b48da113..ff06ce5075 100644 --- a/ui-ngx/src/assets/markers/tripShape4.svg +++ b/ui-ngx/src/assets/markers/tripShape4.svg @@ -1,9 +1,12 @@ - + - - + + diff --git a/ui-ngx/src/assets/markers/tripShape5.svg b/ui-ngx/src/assets/markers/tripShape5.svg index a88d26035d..e774b4f92c 100644 --- a/ui-ngx/src/assets/markers/tripShape5.svg +++ b/ui-ngx/src/assets/markers/tripShape5.svg @@ -1,10 +1,29 @@ - - - + + + + + + + + + + + + + + + + + + + - - + + diff --git a/ui-ngx/src/assets/markers/tripShape6.svg b/ui-ngx/src/assets/markers/tripShape6.svg index 23105baba5..aeb7d7f3f5 100644 --- a/ui-ngx/src/assets/markers/tripShape6.svg +++ b/ui-ngx/src/assets/markers/tripShape6.svg @@ -1,10 +1,29 @@ - - - + + + + + + + + + + + + + + + + + + + - - + + diff --git a/ui-ngx/src/assets/markers/tripShape7.svg b/ui-ngx/src/assets/markers/tripShape7.svg index 342c9db364..38d35f6932 100644 --- a/ui-ngx/src/assets/markers/tripShape7.svg +++ b/ui-ngx/src/assets/markers/tripShape7.svg @@ -1,11 +1,14 @@ - - + + - - + + diff --git a/ui-ngx/src/assets/markers/tripShape8.svg b/ui-ngx/src/assets/markers/tripShape8.svg index f8edbe4dc0..60fdc493c5 100644 --- a/ui-ngx/src/assets/markers/tripShape8.svg +++ b/ui-ngx/src/assets/markers/tripShape8.svg @@ -1,9 +1,12 @@ - + - - + + diff --git a/ui-ngx/src/assets/markers/tripShape9.svg b/ui-ngx/src/assets/markers/tripShape9.svg index 9494a976f0..02521777af 100644 --- a/ui-ngx/src/assets/markers/tripShape9.svg +++ b/ui-ngx/src/assets/markers/tripShape9.svg @@ -1,10 +1,13 @@ - + - - + +