UI: Fix widget edit tooltip. Map - Improve marker icon appearance.

This commit is contained in:
Igor Kulikov 2025-03-06 17:31:00 +02:00
parent e5b8a24598
commit 14de7726c2
20 changed files with 649 additions and 79 deletions

File diff suppressed because one or more lines are too long

View File

@ -53,7 +53,7 @@ import { ImagePipe } from '@shared/pipe/image.pipe';
import { TbMap } from '@home/components/widget/lib/maps/map';
import {
createColorMarkerIconElement,
createColorMarkerShapeURI,
createColorMarkerShapeURI, MarkerIconContainer,
MarkerShape
} from '@shared/models/widget/maps/marker-shape.models';
import { MatIconRegistry } from '@angular/material/icon';
@ -168,8 +168,10 @@ export class MarkerDataProcessor<S extends MarkersDataLayerSettings = MarkersDat
);
}
public createColoredMarkerIcon(icon: string, color: tinycolor.Instance, rotationAngle = 0, size = 34): Observable<MarkerIconInfo> {
return createColorMarkerIconElement(this.dataLayer.getCtx().$injector.get(MatIconRegistry), this.dataLayer.getCtx().$injector.get(DomSanitizer), icon, color, this.trip).pipe(
public createColoredMarkerIcon(iconContainer: MarkerIconContainer,
icon: string, color: tinycolor.Instance, rotationAngle = 0, size = 34): Observable<MarkerIconInfo> {
return createColorMarkerIconElement(this.dataLayer.getCtx().$injector.get(MatIconRegistry), this.dataLayer.getCtx().$injector.get(DomSanitizer),
iconContainer, icon, color, this.trip).pipe(
map((element) => {
if (rotationAngle !== 0) {
element.style.transform = `rotate(${rotationAngle}deg)`;
@ -289,7 +291,7 @@ class IconMarkerIconProcessor extends BaseColorMarkerShapeProcessor<MarkerIconSe
}
protected createMarkerShape(color: tinycolor.Instance, rotationAngle: number, size: number): Observable<MarkerIconInfo> {
return this.dataProcessor.createColoredMarkerIcon(this.settings.icon, color, rotationAngle, size);
return this.dataProcessor.createColoredMarkerIcon(this.settings.iconContainer, this.settings.icon, color, rotationAngle, size);
}
}

View File

@ -15,6 +15,14 @@
*/
@import '../../../../../../../scss/constants';
div.tb-widget .tb-widget-content.tb-no-interaction {
.tb-map {
.leaflet-interactive, .leaflet-control {
pointer-events: none;
}
}
}
.tb-map-container, .tb-map-layout {
position: relative;
display: flex;

View File

@ -224,6 +224,10 @@
</mat-form-field>
</div>
</div>
@if (dataLayerType === 'trips') {
<ng-container *ngTemplateOutlet="dataLayerLabelAndTooltip"></ng-container>
<ng-container *ngTemplateOutlet="behavior; context: {stroked: true}"></ng-container>
}
</div>
<div *ngIf="mapType === MapType.image" class="tb-form-panel stroked">
<div class="tb-form-panel-title" translate>widgets.maps.data-layer.marker.position-conversion</div>
@ -244,7 +248,7 @@
<mat-expansion-panel-header class="flex flex-row flex-wrap">
<mat-panel-title>
<mat-slide-toggle class="mat-slide flex items-stretch justify-center" formControlName="showPath" (click)="$event.stopPropagation()">
{{ 'widgets.maps.data-layer.path.path' | translate }}
<div class="tb-form-panel-title">{{ 'widgets.maps.data-layer.path.path' | translate }}</div>
</mat-slide-toggle>
</mat-panel-title>
</mat-expansion-panel-header>
@ -322,7 +326,7 @@
<mat-expansion-panel-header class="flex flex-row flex-wrap">
<mat-panel-title>
<mat-slide-toggle class="mat-slide flex items-stretch justify-center" formControlName="showPoints" (click)="$event.stopPropagation()">
{{ 'widgets.maps.data-layer.points.points' | translate }}
<div class="tb-form-panel-title">{{ 'widgets.maps.data-layer.points.points' | translate }}</div>
</mat-slide-toggle>
</mat-panel-title>
</mat-expansion-panel-header>
@ -364,32 +368,13 @@
</div>
</div>
</ng-container>
<tb-data-layer-pattern-settings
patternType="label"
[context]="context"
[helpId]="labelHelpId"
formControlName="label">
</tb-data-layer-pattern-settings>
<tb-data-layer-pattern-settings
patternType="tooltip"
[context]="context"
[helpId]="tooltipHelpId"
[hasTooltipOffset]="['trips', 'markers'].includes(dataLayerType)"
formControlName="tooltip">
</tb-data-layer-pattern-settings>
</div>
<div class="tb-form-panel">
<div class="tb-form-panel-title" translate>widgets.maps.data-layer.behavior</div>
<div class="tb-form-row">
<div class="fixed-title-width" tb-hint-tooltip-icon="{{'widgets.maps.data-layer.on-click-hint' | translate}}" translate>widgets.maps.data-layer.on-click</div>
<tb-widget-action-settings class="flex-1"
panelTitle="{{ 'widgets.maps.data-layer.on-click' | translate }}"
[callbacks]="context.callbacks"
[widgetType]="widgetType.latest"
formControlName="click">
</tb-widget-action-settings>
</div>
@if (dataLayerType !== 'trips') {
<ng-container *ngTemplateOutlet="dataLayerLabelAndTooltip"></ng-container>
}
</div>
@if (dataLayerType !== 'trips') {
<ng-container *ngTemplateOutlet="behavior"></ng-container>
}
<div class="tb-form-panel">
<div class="tb-form-panel-title">{{ 'widgets.maps.data-layer.groups' | translate }}</div>
<tb-string-items-list class="tb-inline-chips"
@ -435,3 +420,38 @@
</button>
</div>
</form>
<ng-template #dataLayerLabelAndTooltip>
<ng-container [formGroup]="dataLayerFormGroup">
<tb-data-layer-pattern-settings
patternType="label"
[context]="context"
[helpId]="labelHelpId"
formControlName="label">
</tb-data-layer-pattern-settings>
<tb-data-layer-pattern-settings
patternType="tooltip"
[context]="context"
[helpId]="tooltipHelpId"
[hasTooltipOffset]="['trips', 'markers'].includes(dataLayerType)"
formControlName="tooltip">
</tb-data-layer-pattern-settings>
</ng-container>
</ng-template>
<ng-template #behavior let-stroked="stroked">
<ng-container [formGroup]="dataLayerFormGroup">
<div class="tb-form-panel" [class.stroked]="stroked">
<div class="tb-form-panel-title" translate>widgets.maps.data-layer.behavior</div>
<div class="tb-form-row">
<div class="fixed-title-width" tb-hint-tooltip-icon="{{'widgets.maps.data-layer.on-click-hint' | translate}}" translate>widgets.maps.data-layer.on-click</div>
<tb-widget-action-settings class="flex-1"
panelTitle="{{ 'widgets.maps.data-layer.on-click' | translate }}"
[callbacks]="context.callbacks"
[widgetType]="widgetType.latest"
formControlName="click">
</tb-widget-action-settings>
</div>
</div>
</ng-container>
</ng-template>

View File

@ -0,0 +1,60 @@
<!--
Copyright © 2016-2025 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<div class="tb-marker-icon-shapes-panel">
<div class="tb-marker-icon-shapes-title" translate>widgets.maps.data-layer.marker.marker-icon</div>
<tb-material-icons [selectedIcon]="icon" [iconClearButton]="false" [showTitle]="false"
[popover]="popover" (iconSelected)="selectIcon($event)"></tb-material-icons>
<div class="tb-marker-icon-shapes-title" translate>widgets.maps.data-layer.marker.marker-appearance</div>
<div class="flex flex-row flex-wrap gap-3">
<ng-container *ngFor="let containerInfo of iconContainers">
@if (containerInfo.iconContainer === iconContainer) {
<button class="tb-select-shape-button"
mat-raised-button
(click)="selectIconContainer(containerInfo.iconContainer)"
type="button">
<div class="tb-marker-shape" matButtonIcon [innerHTML]="containerInfo.html$ | async">
</div>
</button>
} @else {
<button class="tb-select-shape-button"
mat-button
(click)="selectIconContainer(containerInfo.iconContainer)"
type="button">
<div class="tb-marker-shape" matButtonIcon [innerHTML]="containerInfo.html$ | async">
</div>
</button>
}
</ng-container>
</div>
<div class="tb-marker-icon-shapes-panel-buttons">
<span class="flex-1"></span>
<button mat-button
color="primary"
type="button"
(click)="cancel()">
{{ 'action.cancel' | translate }}
</button>
<button mat-raised-button
color="primary"
type="button"
(click)="apply()"
[disabled]="!dirty">
{{ 'action.apply' | translate }}
</button>
</div>
</div>

View File

@ -0,0 +1,47 @@
/**
* Copyright © 2016-2025 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.tb-marker-icon-shapes-panel {
width: 100%;
display: flex;
flex-direction: column;
gap: 16px;
.tb-marker-icon-shapes-title {
font-size: 16px;
font-weight: 500;
line-height: 24px;
letter-spacing: 0.25px;
color: rgba(0, 0, 0, 0.87);
}
button.mat-mdc-button-base.tb-select-shape-button {
width: 42px;
min-width: 42px;
height: 42px;
padding: 4px;
div.tb-marker-shape {
width: 34px;
height: 34px;
object-fit: contain;
}
}
.tb-marker-icon-shapes-panel-buttons {
height: 40px;
display: flex;
flex-direction: row;
gap: 16px;
justify-content: flex-end;
align-items: flex-end;
}
}

View File

@ -0,0 +1,127 @@
///
/// Copyright © 2016-2025 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
import { PageComponent } from '@shared/components/page.component';
import { TbPopoverComponent } from '@shared/components/popover.component';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import {
createColorMarkerIconElement,
MarkerIconContainer, markerIconContainers,
tripMarkerIconContainers
} from '@shared/models/widget/maps/marker-shape.models';
import { Observable } from 'rxjs';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { MatIconRegistry } from '@angular/material/icon';
import tinycolor from 'tinycolor2';
import { map, share } from 'rxjs/operators';
import { coerceBoolean } from '@shared/decorators/coercion';
export interface MarkerIconInfo {
iconContainer?: MarkerIconContainer;
icon: string;
}
interface MarkerIconContainerInfo {
iconContainer: MarkerIconContainer;
html$: Observable<SafeHtml>;
}
@Component({
selector: 'tb-marker-icon-shapes',
templateUrl: './marker-icon-shapes.component.html',
providers: [],
styleUrls: ['./marker-icon-shapes.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class MarkerIconShapesComponent extends PageComponent implements OnInit {
@Input()
icon: string;
@Input()
iconContainer: MarkerIconContainer;
@Input()
color: string;
@Input()
@coerceBoolean()
trip = false;
@Input()
popover: TbPopoverComponent<MarkerIconShapesComponent>;
@Output()
markerIconSelected = new EventEmitter<MarkerIconInfo>();
dirty = false;
iconContainers: MarkerIconContainerInfo[];
constructor(protected store: Store<AppState>,
private iconRegistry: MatIconRegistry,
private domSanitizer: DomSanitizer) {
super(store);
}
ngOnInit(): void {
this.updateIconContainers();
}
cancel() {
this.popover?.hide();
}
selectIcon(icon: string) {
if (this.icon !== icon) {
this.icon = icon;
this.dirty = true;
this.updateIconContainers();
}
}
selectIconContainer(iconContainer: MarkerIconContainer) {
if (this.iconContainer !== iconContainer) {
this.iconContainer = iconContainer;
this.dirty = true;
}
}
apply() {
const iconInfo: MarkerIconInfo = {
iconContainer: this.iconContainer,
icon: this.icon
};
this.markerIconSelected.emit(iconInfo);
}
private updateIconContainers() {
const containersList = [...(this.trip ? tripMarkerIconContainers : markerIconContainers),null];
this.iconContainers = containersList.map((iconContainer) => {
return {
iconContainer,
html$: createColorMarkerIconElement(this.iconRegistry, this.domSanitizer, iconContainer, this.icon, tinycolor(this.color), this.trip).pipe(
map((element) => {
return this.domSanitizer.bypassSecurityTrustHtml(element.outerHTML);
}),
share()
)
};
});
}
}

View File

@ -45,8 +45,10 @@ import {
import tinycolor from 'tinycolor2';
import { map, share } from 'rxjs/operators';
import { MarkerShapesComponent } from '@home/components/widget/lib/settings/common/map/marker-shapes.component';
import { MaterialIconsComponent } from '@shared/components/material-icons.component';
import { coerceBoolean } from '@shared/decorators/coercion';
import {
MarkerIconShapesComponent
} from '@home/components/widget/lib/settings/common/map/marker-icon-shapes.component';
@Component({
selector: 'tb-marker-shape-settings',
@ -89,7 +91,6 @@ export class MarkerShapeSettingsComponent implements ControlValueAccessor, OnIni
private iconRegistry: MatIconRegistry,
private domSanitizer: DomSanitizer,
private renderer: Renderer2,
private cd: ChangeDetectorRef,
private viewContainerRef: ViewContainerRef) {}
ngOnInit(): void {
@ -101,6 +102,7 @@ export class MarkerShapeSettingsComponent implements ControlValueAccessor, OnIni
this.shapeSettingsFormGroup.addControl('shape', this.fb.control(null, [Validators.required]));
}
if (this.markerType === MarkerType.icon) {
this.shapeSettingsFormGroup.addControl('iconContainer', this.fb.control(null, []));
this.shapeSettingsFormGroup.addControl('icon', this.fb.control(null, [Validators.required]));
}
this.shapeSettingsFormGroup.valueChanges.pipe(
@ -162,20 +164,26 @@ export class MarkerShapeSettingsComponent implements ControlValueAccessor, OnIni
});
} else if (this.markerType === MarkerType.icon) {
const ctx: any = {
selectedIcon: (this.modelValue as MarkerIconSettings).icon,
iconClearButton: false
iconContainer: (this.modelValue as MarkerIconSettings).iconContainer,
icon: (this.modelValue as MarkerIconSettings).icon,
color: this.modelValue.color.color,
trip: this.trip
};
const materialIconsPopover = this.popoverService.displayPopover(trigger, this.renderer,
this.viewContainerRef, MaterialIconsComponent, 'left', true, null,
const markerIconShapesPopover = this.popoverService.displayPopover(trigger, this.renderer,
this.viewContainerRef, MarkerIconShapesComponent, 'left', true, null,
ctx,
{},
{}, {}, true);
materialIconsPopover.tbComponentRef.instance.popover = materialIconsPopover;
materialIconsPopover.tbComponentRef.instance.iconSelected.subscribe((icon) => {
materialIconsPopover.hide();
this.shapeSettingsFormGroup.get('icon').patchValue(
icon
markerIconShapesPopover.tbComponentRef.instance.popover = markerIconShapesPopover;
markerIconShapesPopover.tbComponentRef.instance.markerIconSelected.subscribe((iconInfo) => {
markerIconShapesPopover.hide();
this.shapeSettingsFormGroup.get('iconContainer').patchValue(
iconInfo.iconContainer, {emitEvent: false}
);
this.shapeSettingsFormGroup.get('icon').patchValue(
iconInfo.icon, {emitEvent: false}
);
this.updateModel();
});
}
}
@ -198,8 +206,9 @@ export class MarkerShapeSettingsComponent implements ControlValueAccessor, OnIni
share()
);
} 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, icon, tinycolor(color), this.trip).pipe(
this.iconPreview$ = createColorMarkerIconElement(this.iconRegistry, this.domSanitizer, iconContainer, icon, tinycolor(color), this.trip).pipe(
map((element) => {
return this.domSanitizer.bypassSecurityTrustHtml(element.outerHTML);
}),

View File

@ -245,6 +245,9 @@ import {
import {
TripTimelineSettingsComponent
} from '@home/components/widget/lib/settings/common/map/trip-timeline-settings.component';
import {
MarkerIconShapesComponent
} from '@home/components/widget/lib/settings/common/map/marker-icon-shapes.component';
@NgModule({
declarations: [
@ -327,6 +330,7 @@ import {
DataLayerPatternSettingsComponent,
MarkerShapeSettingsComponent,
MarkerShapesComponent,
MarkerIconShapesComponent,
MarkerImageSettingsComponent,
MarkerImageSettingsPanelComponent,
MarkerClusteringSettingsComponent,

View File

@ -45,6 +45,7 @@ import { UtilsService } from '@core/services/utils.service';
import { from } from 'rxjs';
import { DashboardUtilsService } from '@core/services/dashboard-utils.service';
import ITooltipsterInstance = JQueryTooltipster.ITooltipsterInstance;
import ITooltipsterGeoHelper = JQueryTooltipster.ITooltipsterGeoHelper;
import { TbContextMenuEvent } from '@shared/models/jquery-event.models';
export enum WidgetComponentActionType {
@ -124,7 +125,6 @@ export class WidgetContainerComponent extends PageComponent implements OnInit, O
widgetComponentAction: EventEmitter<WidgetComponentAction> = new EventEmitter<WidgetComponentAction>();
hovered = false;
isReferenceWidget = false;
get widgetEditActionsEnabled(): boolean {
return (this.isEditActionEnabled || this.isRemoveActionEnabled || this.isExportActionEnabled) && !this.widget?.isFullscreen;
@ -295,6 +295,7 @@ export class WidgetContainerComponent extends PageComponent implements OnInit, O
theme: ['tb-widget-edit-actions-tooltip'],
interactive: true,
trigger: 'custom',
ignoreCloseOnScroll: true,
triggerOpen: {
mouseenter: true
},
@ -305,6 +306,9 @@ export class WidgetContainerComponent extends PageComponent implements OnInit, O
trackOrigin: true,
trackerInterval: 25,
content: '',
checkOverflowY: (geo: ITooltipsterGeoHelper, bcr: DOMRect) => {
return geo.origin.windowOffset.top < bcr.top || geo.origin.windowOffset.bottom < bcr.bottom;
},
functionPosition: (instance, helper, position) => {
const clientRect = helper.origin.getBoundingClientRect();
const container = parent.getBoundingClientRect();
@ -314,6 +318,7 @@ export class WidgetContainerComponent extends PageComponent implements OnInit, O
return position;
},
functionReady: (_instance, helper) => {
this.editWidgetActionsTooltip.__scrollHandler({});
const tooltipEl = $(helper.tooltip);
tooltipEl.on('mouseenter', () => {
this.hovered = true;

View File

@ -16,7 +16,7 @@
-->
<div class="tb-material-icons-panel">
<div class="tb-material-icons-title" translate>icon.icons</div>
<div *ngIf="showTitle" class="tb-material-icons-title" translate>icon.icons</div>
<mat-form-field class="tb-material-icons-search tb-inline-field" appearance="outline" subscriptSizing="dynamic">
<mat-icon matPrefix>search</mat-icon>
<input matInput [formControl]="searchIconControl" placeholder="{{ 'icon.search-icon' | translate }}"/>

View File

@ -58,7 +58,11 @@ export class MaterialIconsComponent extends PageComponent implements OnInit {
iconClearButton = false;
@Input()
popover: TbPopoverComponent<MaterialIconsComponent>;
@coerceBoolean()
showTitle = true;
@Input()
popover: TbPopoverComponent;
@Output()
iconSelected = new EventEmitter<string>();

View File

@ -28,18 +28,19 @@ import {
hashCode,
isDefinedAndNotNull,
isNotEmptyStr,
isNumber,
isString,
isUndefinedOrNull,
mergeDeep
} from '@core/utils';
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';
import { materialColors } from '@shared/models/material.models';
import L from 'leaflet';
import type L from 'leaflet';
import { TbFunction } from '@shared/models/js-function.models';
import { Observable, Observer, of, switchMap } from 'rxjs';
import { map } from 'rxjs/operators';
import { ImagePipe } from '@shared/pipe/image.pipe';
import { MarkerShape } from '@shared/models/widget/maps/marker-shape.models';
import { MarkerIconContainer, MarkerShape } from '@shared/models/widget/maps/marker-shape.models';
import { DateFormatSettings, simpleDateFormat } from '@shared/models/widget-settings.models';
export enum MapType {
@ -262,6 +263,7 @@ export interface MarkerShapeSettings extends BaseMarkerShapeSettings {
}
export interface MarkerIconSettings extends BaseMarkerShapeSettings {
iconContainer?: MarkerIconContainer;
icon: string;
}
export interface MarkerClusteringSettings {
@ -352,6 +354,7 @@ export const defaultBaseMarkersDataLayerSettings = (mapType: MapType): Partial<M
}
},
markerIcon: {
iconContainer: MarkerIconContainer.iconContainer1,
icon: 'mdi:lightbulb-on',
size: 48,
color: {
@ -434,6 +437,7 @@ export const defaultBaseTripsDataLayerSettings = (mapType: MapType): Partial<Tri
shape: MarkerShape.tripMarkerShape1
},
markerIcon: {
iconContainer: MarkerIconContainer.tripIconContainer1,
icon: 'arrow_forward'
},
markerImage: {
@ -1090,7 +1094,7 @@ export const isValidLatLng = (latitude: any, longitude: any): boolean =>
isValidLatitude(latitude) && isValidLongitude(longitude);
export const isCutPolygon = (data: TbPolygonCoordinates | TbPolygonRawCoordinates): boolean => {
return data.length > 1 && Array.isArray(data[0]) && (Array.isArray(data[0][0]) || data[0][0] instanceof L.LatLng);
return data.length > 1 && Array.isArray(data[0]) && (Array.isArray(data[0][0]) || (isNumber((data[0][0] as any).lat) && isNumber((data[0][0] as any).lng)) );
}
export const parseCenterPosition = (position: string | [number, number]): [number, number] => {

View File

@ -20,7 +20,7 @@ import { DomSanitizer } from '@angular/platform-browser';
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, Text } from '@svgdotjs/svg.js';
import { Element, G, SVG, Text } from '@svgdotjs/svg.js';
export enum MarkerShape {
markerShape1 = 'markerShape1',
@ -45,6 +45,11 @@ export enum MarkerShape {
tripMarkerShape10 = 'tripMarkerShape10'
}
export enum MarkerIconContainer {
iconContainer1 = 'iconContainer1',
tripIconContainer1 = 'tripIconContainer1'
}
export const markerShapeMap = new Map<MarkerShape, string>(
[
[MarkerShape.markerShape1, '/assets/markers/shape1.svg'],
@ -70,6 +75,13 @@ export const markerShapeMap = new Map<MarkerShape, string>(
]
);
export const markerIconContainerMap = new Map<MarkerIconContainer, string>(
[
[MarkerIconContainer.iconContainer1, '/assets/markers/iconContainer1.svg'],
[MarkerIconContainer.tripIconContainer1, '/assets/markers/tripIconContainer1.svg']
]
);
export const markerShapes = [
MarkerShape.markerShape1,
MarkerShape.markerShape2,
@ -96,9 +108,11 @@ export const tripMarkerShapes = [
MarkerShape.tripMarkerShape10
];
const createColorMarkerShape = (iconRegistry: MatIconRegistry, domSanitizer: DomSanitizer, shape: MarkerShape, color: tinycolor.Instance): Observable<SVGElement> => {
const markerAssetUrl = markerShapeMap.get(shape);
const safeUrl = domSanitizer.bypassSecurityTrustResourceUrl(markerAssetUrl);
export const markerIconContainers = [ MarkerIconContainer.iconContainer1 ];
export const tripMarkerIconContainers = [ MarkerIconContainer.tripIconContainer1 ];
const createColorMarkerShape = (iconRegistry: MatIconRegistry, domSanitizer: DomSanitizer, assetUrl: string, color: tinycolor.Instance): Observable<SVGElement> => {
const safeUrl = domSanitizer.bypassSecurityTrustResourceUrl(assetUrl);
return iconRegistry.getSvgIconFromUrl(safeUrl).pipe(
map((svgElement) => {
const colorElements = Array.from(svgElement.getElementsByClassName('marker-color'));
@ -124,7 +138,8 @@ const createColorMarkerShape = (iconRegistry: MatIconRegistry, domSanitizer: Dom
export const createColorMarkerShapeURI = (iconRegistry: MatIconRegistry, domSanitizer: DomSanitizer, shape: MarkerShape, color: tinycolor.Instance): Observable<string> => {
return createColorMarkerShape(iconRegistry, domSanitizer, shape, color).pipe(
const assetUrl = markerShapeMap.get(shape);
return createColorMarkerShape(iconRegistry, domSanitizer, assetUrl, color).pipe(
map((svgElement) => {
const svg = svgElement.outerHTML;
return 'data:image/svg+xml;base64,' + btoa(svg);
@ -174,29 +189,38 @@ const createIconElement = (iconRegistry: MatIconRegistry, icon: string, size: nu
}
}
const markerIconShape = MarkerShape.markerShape6;
const tripMarkerIconShape = MarkerShape.tripMarkerShape2;
export const createColorMarkerIconElement = (iconRegistry: MatIconRegistry, domSanitizer: DomSanitizer, icon: string, color: tinycolor.Instance,
export const createColorMarkerIconElement = (iconRegistry: MatIconRegistry, domSanitizer: DomSanitizer,
iconContainer: MarkerIconContainer, icon: string, color: tinycolor.Instance,
trip = false): Observable<SVGElement> => {
return createColorMarkerShape(iconRegistry, domSanitizer, trip ? tripMarkerIconShape : markerIconShape, color).pipe(
const markerShape$: Observable<SVGElement> = iconContainer ?
createColorMarkerShape(iconRegistry, domSanitizer, markerIconContainerMap.get(iconContainer), color) : of(null);
return markerShape$.pipe(
switchMap((svgElement) => {
return createIconElement(iconRegistry, icon, trip ? 24 : 12, trip ? tinycolor('#fff') : color, trip).pipe(
const iconSize = svgElement ? (trip ? 24 : 12) : 24;
const iconColor = svgElement ? (trip ? tinycolor('#fff') : color) : color;
return createIconElement(iconRegistry, icon, iconSize, iconColor, trip || !svgElement).pipe(
map((iconElement) => {
let elements = svgElement.getElementsByClassName('marker-icon-container');
if (iconElement && elements.length) {
const iconContainer = new G(elements[0] as SVGGElement);
iconContainer.clear();
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);
}
return svgElement;
} else {
const svg = SVG();
svg.viewbox(0,0,iconSize,iconSize);
const iconContainer = new G();
iconContainer.translate(iconSize/2,iconSize/2);
iconContainer.add(iconElement);
const box = iconElement.bbox();
iconElement.translate(-box.cx, -box.cy);
svg.add(iconContainer);
return svg.node;
}
elements = svgElement.getElementsByClassName('marker-icon-background');
if (elements.length) {
(elements[0] as SVGGElement).style.display = '';
(elements[0] as SVGGElement).setAttribute('fill-opacity', `${color.getAlpha()}`);
}
return svgElement;
})
);
})

View File

@ -7869,6 +7869,8 @@
"icon": "Icon",
"image": "Image",
"marker-shapes": "Marker shapes",
"marker-icon": "Marker icon",
"marker-appearance": "Marker appearance",
"marker-image": "Marker image",
"marker-image-type-image": "Image",
"marker-image-type-function": "Function",

View File

@ -0,0 +1,22 @@
<svg xmlns="http://www.w3.org/2000/svg" width="34" height="34" viewBox="0 0 34 34" class="marker-color" fill="#307FE5">
<g filter="url(#filter0_bf_8817_262071)">
<path d="M19 24.5C17.4075 27.4125 17 33 17 33C17 33 27.0858 32.1955 30.9992 27.4998C34 23.8992 31.9992 19 27.9992 19C23.9993 19 21.1929 20.4894 19 24.5Z" fill="black" fill-opacity="0.24"/>
</g>
<mask id="path-2-inside-1_8817_262071" fill="white">
<path fill-rule="evenodd" clip-rule="evenodd" d="M30 12.9625C30 6.39011 25.6157 0 17 0C8.38434 0 4 6.39011 4 12.9625C4 25 17 34 17 34C17 34 30 25 30 12.9625ZM26 13C26 17.9706 21.9706 22 17 22C12.0294 22 8 17.9706 8 13C8 8.02944 12.0294 4 17 4C21.9706 4 26 8.02944 26 13Z"/>
</mask>
<path fill-rule="evenodd" clip-rule="evenodd" d="M30 12.9625C30 6.39011 25.6157 0 17 0C8.38434 0 4 6.39011 4 12.9625C4 25 17 34 17 34C17 34 30 25 30 12.9625ZM26 13C26 17.9706 21.9706 22 17 22C12.0294 22 8 17.9706 8 13C8 8.02944 12.0294 4 17 4C21.9706 4 26 8.02944 26 13Z"/>
<path d="M17 34L16.3952 34.8736L17 35.2923L17.6048 34.8736L17 34ZM17 1.0625C21.024 1.0625 23.9805 2.54472 25.9405 4.72663C27.9167 6.92661 28.9375 9.90415 28.9375 12.9625H31.0625C31.0625 9.44846 29.8911 5.94475 27.5213 3.30657C25.1352 0.650333 21.5917 -1.0625 17 -1.0625V1.0625ZM5.0625 12.9625C5.0625 9.90415 6.08332 6.92661 8.05955 4.72663C10.0195 2.54472 12.976 1.0625 17 1.0625V-1.0625C12.4083 -1.0625 8.86479 0.650333 6.47871 3.30657C4.10885 5.94475 2.9375 9.44846 2.9375 12.9625H5.0625ZM17 34C17.6048 33.1264 17.605 33.1266 17.6052 33.1267C17.6052 33.1267 17.6053 33.1268 17.6053 33.1268C17.6052 33.1267 17.605 33.1266 17.6046 33.1263C17.6037 33.1257 17.6021 33.1245 17.5997 33.1229C17.5949 33.1195 17.587 33.114 17.5762 33.1063C17.5546 33.091 17.5211 33.0672 17.4766 33.035C17.3876 32.9706 17.2545 32.8729 17.0835 32.7432C16.7414 32.4838 16.2486 32.0971 15.6553 31.5948C14.4672 30.5889 12.884 29.126 11.3033 27.2999C8.11939 23.6215 5.0625 18.605 5.0625 12.9625H2.9375C2.9375 19.3575 6.38061 24.8597 9.69665 28.6907C11.366 30.6193 13.0328 32.1588 14.2822 33.2166C14.9077 33.7461 15.4305 34.1565 15.7993 34.4363C15.9838 34.5763 16.13 34.6836 16.2314 34.7569C16.2821 34.7936 16.3216 34.8218 16.3492 34.8413C16.363 34.851 16.3738 34.8586 16.3815 34.864C16.3853 34.8667 16.3884 34.8688 16.3907 34.8704C16.3918 34.8712 16.3928 34.8719 16.3935 34.8724C16.3939 34.8727 16.3943 34.873 16.3945 34.8731C16.3949 34.8734 16.3952 34.8736 17 34ZM28.9375 12.9625C28.9375 18.605 25.8806 23.6215 22.6966 27.2999C21.116 29.126 19.5328 30.5889 18.3447 31.5948C17.7514 32.0971 17.2586 32.4838 16.9165 32.7432C16.7455 32.8729 16.6124 32.9706 16.5234 33.035C16.4789 33.0672 16.4454 33.091 16.4238 33.1063C16.413 33.114 16.4051 33.1195 16.4003 33.1229C16.3979 33.1245 16.3963 33.1257 16.3954 33.1263C16.395 33.1266 16.3948 33.1267 16.3947 33.1268C16.3947 33.1268 16.3948 33.1267 16.3948 33.1267C16.395 33.1266 16.3952 33.1264 17 34C17.6048 34.8736 17.6051 34.8734 17.6055 34.8731C17.6057 34.873 17.6061 34.8727 17.6065 34.8724C17.6072 34.8719 17.6082 34.8712 17.6093 34.8704C17.6116 34.8688 17.6147 34.8667 17.6185 34.864C17.6262 34.8586 17.637 34.851 17.6508 34.8413C17.6784 34.8218 17.7179 34.7936 17.7686 34.7569C17.87 34.6836 18.0162 34.5763 18.2007 34.4363C18.5695 34.1565 19.0923 33.7461 19.7178 33.2166C20.9672 32.1588 22.634 30.6193 24.3034 28.6907C27.6194 24.8597 31.0625 19.3575 31.0625 12.9625H28.9375ZM17 23.0625C22.5574 23.0625 27.0625 18.5574 27.0625 13H24.9375C24.9375 17.3838 21.3838 20.9375 17 20.9375V23.0625ZM6.9375 13C6.9375 18.5574 11.4426 23.0625 17 23.0625V20.9375C12.6162 20.9375 9.0625 17.3838 9.0625 13H6.9375ZM17 2.9375C11.4426 2.9375 6.9375 7.44263 6.9375 13H9.0625C9.0625 8.61624 12.6162 5.0625 17 5.0625V2.9375ZM27.0625 13C27.0625 7.44263 22.5574 2.9375 17 2.9375V5.0625C21.3838 5.0625 24.9375 8.61624 24.9375 13H27.0625Z" fill="black" fill-opacity="0.38" mask="url(#path-2-inside-1_8817_262071)"/>
<circle cx="17" cy="13" r="9" fill="#fff"></circle>
<g class="marker-icon-container" transform="translate(17,13)">
</g>
<defs>
<filter id="filter0_bf_8817_262071" x="12.75" y="14.75" width="23.9434" height="22.5" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feGaussianBlur in="BackgroundImageFix" stdDeviation="2.125"/>
<feComposite in2="SourceAlpha" operator="in" result="effect1_backgroundBlur_8817_262071"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_backgroundBlur_8817_262071" result="shape"/>
<feGaussianBlur stdDeviation="0.5" result="effect2_foregroundBlur_8817_262071"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -1,11 +1,11 @@
<svg xmlns="http://www.w3.org/2000/svg" width="34" height="34" viewBox="0 0 34 34" fill="none">
<svg xmlns="http://www.w3.org/2000/svg" width="34" height="34" viewBox="0 0 34 34" class="marker-color" fill="#307FE5">
<g filter="url(#filter0_bf_8816_263887)">
<path d="M19 24.5C17.4075 27.4125 17 33 17 33C17 33 27.0858 32.1955 30.9992 27.4998C34 23.8992 31.9992 19 27.9992 19C23.9993 19 21.1929 20.4894 19 24.5Z" fill="black" fill-opacity="0.24"/>
</g>
<mask id="path-2-inside-1_8816_263887" fill="white">
<path fill-rule="evenodd" clip-rule="evenodd" d="M28 11.9C28.0037 5.32761 24.2902 0 17 0C9.70983 0 5.9963 5.32761 6 11.9C6.00473 20.2937 17 34 17 34C17 34 27.9953 20.2937 28 11.9ZM21.25 10.625C21.25 12.9722 19.3472 14.875 17 14.875C14.6528 14.875 12.75 12.9722 12.75 10.625C12.75 8.27779 14.6528 6.375 17 6.375C19.3472 6.375 21.25 8.27779 21.25 10.625Z"/>
</mask>
<path class="marker-color" fill-rule="evenodd" clip-rule="evenodd" d="M28 11.9C28.0037 5.32761 24.2902 0 17 0C9.70983 0 5.9963 5.32761 6 11.9C6.00473 20.2937 17 34 17 34C17 34 27.9953 20.2937 28 11.9ZM21.25 10.625C21.25 12.9722 19.3472 14.875 17 14.875C14.6528 14.875 12.75 12.9722 12.75 10.625C12.75 8.27779 14.6528 6.375 17 6.375C19.3472 6.375 21.25 8.27779 21.25 10.625Z" fill="#307FE5"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M28 11.9C28.0037 5.32761 24.2902 0 17 0C9.70983 0 5.9963 5.32761 6 11.9C6.00473 20.2937 17 34 17 34C17 34 27.9953 20.2937 28 11.9ZM21.25 10.625C21.25 12.9722 19.3472 14.875 17 14.875C14.6528 14.875 12.75 12.9722 12.75 10.625C12.75 8.27779 14.6528 6.375 17 6.375C19.3472 6.375 21.25 8.27779 21.25 10.625Z"/>
<path d="M28 11.9L29.0625 11.9006L28 11.9ZM6 11.9L7.0625 11.8994L6 11.9ZM17 34L16.1712 34.6649L17 35.698L17.8288 34.6649L17 34ZM17 1.0625C20.3641 1.0625 22.8085 2.28006 24.4273 4.17539C26.0652 6.09323 26.9392 8.80331 26.9375 11.8994L29.0625 11.9006C29.0644 8.4243 28.0835 5.18438 26.0431 2.79532C23.9835 0.383742 20.9261 -1.0625 17 -1.0625V1.0625ZM7.0625 11.8994C7.06076 8.80331 7.93477 6.09323 9.57274 4.17539C11.1915 2.28006 13.6359 1.0625 17 1.0625V-1.0625C13.0739 -1.0625 10.0165 0.383741 7.95686 2.79532C5.91645 5.18438 4.93555 8.4243 4.9375 11.9006L7.0625 11.8994ZM17 34C17.8288 33.3351 17.8288 33.3352 17.8288 33.3352C17.8288 33.3352 17.8288 33.3351 17.8287 33.335C17.8285 33.3348 17.8281 33.3343 17.8276 33.3336C17.8265 33.3323 17.8248 33.3301 17.8224 33.3271C17.8176 33.3212 17.8103 33.312 17.8004 33.2995C17.7807 33.2747 17.7509 33.2371 17.7118 33.1874C17.6335 33.0878 17.5178 32.9395 17.37 32.7472C17.0742 32.3624 16.6503 31.8017 16.1409 31.1019C15.1214 29.7014 13.7634 27.7495 12.4071 25.5415C11.049 23.3306 9.70388 20.8813 8.70091 18.4841C7.69109 16.0706 7.06357 13.7921 7.0625 11.8994L4.9375 11.9006C4.9388 14.2048 5.68746 16.7873 6.74058 19.3043C7.80055 21.8378 9.20516 24.3889 10.5964 26.6538C11.9895 28.9216 13.3807 30.9209 14.4229 32.3526C14.9444 33.0689 15.3795 33.6446 15.6851 34.0422C15.8379 34.241 15.9584 34.3954 16.0412 34.5007C16.0826 34.5534 16.1146 34.5938 16.1365 34.6213C16.1474 34.6351 16.1559 34.6456 16.1617 34.6529C16.1646 34.6566 16.1668 34.6594 16.1684 34.6614C16.1692 34.6624 16.1699 34.6632 16.1703 34.6637C16.1706 34.664 16.1708 34.6643 16.1709 34.6645C16.1711 34.6647 16.1712 34.6649 17 34ZM26.9375 11.8994C26.9364 13.7921 26.3089 16.0706 25.2991 18.4841C24.2961 20.8813 22.951 23.3306 21.5929 25.5415C20.2366 27.7495 18.8786 29.7014 17.8591 31.1019C17.3497 31.8017 16.9258 32.3624 16.63 32.7472C16.4822 32.9395 16.3665 33.0878 16.2882 33.1874C16.2491 33.2371 16.2193 33.2747 16.1996 33.2995C16.1897 33.312 16.1824 33.3212 16.1776 33.3271C16.1752 33.3301 16.1735 33.3323 16.1724 33.3336C16.1719 33.3343 16.1715 33.3348 16.1713 33.335C16.1712 33.3351 16.1712 33.3352 16.1712 33.3352C16.1712 33.3352 16.1712 33.3351 17 34C17.8288 34.6649 17.8289 34.6647 17.8291 34.6645C17.8292 34.6643 17.8294 34.664 17.8297 34.6637C17.8301 34.6632 17.8308 34.6624 17.8316 34.6614C17.8332 34.6594 17.8354 34.6566 17.8383 34.6529C17.8441 34.6456 17.8526 34.6351 17.8635 34.6213C17.8854 34.5938 17.9174 34.5534 17.9588 34.5007C18.0416 34.3954 18.1621 34.241 18.3149 34.0422C18.6205 33.6446 19.0556 33.0689 19.5771 32.3526C20.6193 30.9209 22.0105 28.9216 23.4036 26.6538C24.7948 24.3889 26.1995 21.8378 27.2594 19.3043C28.3125 16.7873 29.0612 14.2048 29.0625 11.9006L26.9375 11.8994ZM17 15.9375C19.934 15.9375 22.3125 13.559 22.3125 10.625H20.1875C20.1875 12.3854 18.7604 13.8125 17 13.8125V15.9375ZM11.6875 10.625C11.6875 13.559 14.066 15.9375 17 15.9375V13.8125C15.2396 13.8125 13.8125 12.3854 13.8125 10.625H11.6875ZM17 5.3125C14.066 5.3125 11.6875 7.69099 11.6875 10.625H13.8125C13.8125 8.86459 15.2396 7.4375 17 7.4375V5.3125ZM22.3125 10.625C22.3125 7.69099 19.934 5.3125 17 5.3125V7.4375C18.7604 7.4375 20.1875 8.86459 20.1875 10.625H22.3125Z" fill="black" fill-opacity="0.38" mask="url(#path-2-inside-1_8816_263887)"/>
<defs>
<filter id="filter0_bf_8816_263887" x="12.75" y="14.75" width="23.9434" height="22.5" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -1,8 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="34" height="34" viewBox="0 0 34 34" fill="none">
<svg xmlns="http://www.w3.org/2000/svg" width="34" height="34" viewBox="0 0 34 34" class="marker-color" fill="#307FE5">
<g filter="url(#filter0_bf_8816_263882)">
<path d="M19 24.5C17.4075 27.4125 17 33 17 33C17 33 27.0858 32.1955 30.9992 27.4998C34 23.8992 31.9992 19 27.9992 19C23.9993 19 21.1929 20.4894 19 24.5Z" fill="black" fill-opacity="0.24"/>
</g>
<path class="marker-color" d="M16.8812 33.8865C16.8452 33.7872 16.6641 33.1184 16.4788 32.4005C15.8927 30.1293 14.8789 27.6872 13.5032 25.2321C12.7133 23.8226 12.5705 23.598 10.2629 20.135C6.53418 14.5396 5.8789 12.9684 6.01669 9.95493C6.14303 7.19334 7.10838 5.12431 9.20388 3.12359C10.9433 1.46297 12.8739 0.5051 15.2223 0.13773C21.0423 -0.772682 26.6886 2.92621 27.8326 8.39854C28.0993 9.67434 28.0401 11.87 27.7068 13.0629C27.3412 14.3714 25.8745 17.0188 23.8016 20.1115C20.0603 25.6936 18.6436 28.4817 17.5828 32.3508C17.1722 33.8487 17.0023 34.2205 16.8812 33.8865Z" fill="#307FE5"/>
<path d="M16.8812 33.8865C16.8452 33.7872 16.6641 33.1184 16.4788 32.4005C15.8927 30.1293 14.8789 27.6872 13.5032 25.2321C12.7133 23.8226 12.5705 23.598 10.2629 20.135C6.53418 14.5396 5.8789 12.9684 6.01669 9.95493C6.14303 7.19334 7.10838 5.12431 9.20388 3.12359C10.9433 1.46297 12.8739 0.5051 15.2223 0.13773C21.0423 -0.772682 26.6886 2.92621 27.8326 8.39854C28.0993 9.67434 28.0401 11.87 27.7068 13.0629C27.3412 14.3714 25.8745 17.0188 23.8016 20.1115C20.0603 25.6936 18.6436 28.4817 17.5828 32.3508C17.1722 33.8487 17.0023 34.2205 16.8812 33.8865Z"/>
<path d="M10.2663 20.1328L10.705 19.8404C13.012 23.3025 13.1655 23.5428 13.9666 24.9724L13.5032 25.2321L13.9666 24.9724C15.3604 27.4598 16.3936 29.9445 16.9932 32.2677C17.0031 32.3062 17.013 32.3445 17.0229 32.3826C17.0383 32.3272 17.0542 32.2698 17.0705 32.2103C18.1532 28.2612 19.6055 25.4179 23.3603 19.8157L23.8016 20.1115L23.3604 19.8157C24.3907 18.2785 25.2672 16.8565 25.9298 15.6607C26.5985 14.4537 27.0302 13.5105 27.1952 12.9199C27.3454 12.3823 27.4411 11.5835 27.4636 10.7475C27.4861 9.91291 27.4344 9.08999 27.3126 8.50725C26.2313 3.33526 20.8692 -0.207891 15.3044 0.662597C13.0643 1.01301 11.2327 1.92108 9.57073 3.50784M10.2663 20.1328L6.54738 9.97919C6.66715 7.36131 7.56888 5.41915 9.57073 3.50784M10.2663 20.1328L10.705 19.8404C8.83761 17.0382 7.77024 15.287 7.18016 13.8723M10.2663 20.1328L7.18016 13.8723M9.57073 3.50784L9.20388 3.12359L9.57073 3.50784ZM7.18016 13.8723C6.60389 12.4906 6.48125 11.4256 6.54738 9.97921L7.18016 13.8723Z" stroke="black" stroke-opacity="0.38" stroke-width="1.0625"/>
<path d="M20 11C20 12.6568 18.6569 14 17 14C15.3432 14 14 12.6568 14 11C14 9.3431 15.3431 8 17 8C18.6569 8 20 9.3431 20 11Z" fill="black" fill-opacity="0.38"/>
<defs>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -1,15 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" width="34" height="34" viewBox="0 0 34 34" fill="none">
<svg xmlns="http://www.w3.org/2000/svg" width="34" height="34" viewBox="0 0 34 34" class="marker-color" fill="#307FE5">
<g filter="url(#filter0_bf_8817_262071)">
<path d="M19 24.5C17.4075 27.4125 17 33 17 33C17 33 27.0858 32.1955 30.9992 27.4998C34 23.8992 31.9992 19 27.9992 19C23.9993 19 21.1929 20.4894 19 24.5Z" fill="black" fill-opacity="0.24"/>
</g>
<mask id="path-2-inside-1_8817_262071" fill="white">
<path fill-rule="evenodd" clip-rule="evenodd" d="M30 12.9625C30 6.39011 25.6157 0 17 0C8.38434 0 4 6.39011 4 12.9625C4 25 17 34 17 34C17 34 30 25 30 12.9625ZM26 13C26 17.9706 21.9706 22 17 22C12.0294 22 8 17.9706 8 13C8 8.02944 12.0294 4 17 4C21.9706 4 26 8.02944 26 13Z"/>
</mask>
<path class="marker-color" fill-rule="evenodd" clip-rule="evenodd" d="M30 12.9625C30 6.39011 25.6157 0 17 0C8.38434 0 4 6.39011 4 12.9625C4 25 17 34 17 34C17 34 30 25 30 12.9625ZM26 13C26 17.9706 21.9706 22 17 22C12.0294 22 8 17.9706 8 13C8 8.02944 12.0294 4 17 4C21.9706 4 26 8.02944 26 13Z" fill="#307FE5"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M30 12.9625C30 6.39011 25.6157 0 17 0C8.38434 0 4 6.39011 4 12.9625C4 25 17 34 17 34C17 34 30 25 30 12.9625ZM26 13C26 17.9706 21.9706 22 17 22C12.0294 22 8 17.9706 8 13C8 8.02944 12.0294 4 17 4C21.9706 4 26 8.02944 26 13Z"/>
<path d="M17 34L16.3952 34.8736L17 35.2923L17.6048 34.8736L17 34ZM17 1.0625C21.024 1.0625 23.9805 2.54472 25.9405 4.72663C27.9167 6.92661 28.9375 9.90415 28.9375 12.9625H31.0625C31.0625 9.44846 29.8911 5.94475 27.5213 3.30657C25.1352 0.650333 21.5917 -1.0625 17 -1.0625V1.0625ZM5.0625 12.9625C5.0625 9.90415 6.08332 6.92661 8.05955 4.72663C10.0195 2.54472 12.976 1.0625 17 1.0625V-1.0625C12.4083 -1.0625 8.86479 0.650333 6.47871 3.30657C4.10885 5.94475 2.9375 9.44846 2.9375 12.9625H5.0625ZM17 34C17.6048 33.1264 17.605 33.1266 17.6052 33.1267C17.6052 33.1267 17.6053 33.1268 17.6053 33.1268C17.6052 33.1267 17.605 33.1266 17.6046 33.1263C17.6037 33.1257 17.6021 33.1245 17.5997 33.1229C17.5949 33.1195 17.587 33.114 17.5762 33.1063C17.5546 33.091 17.5211 33.0672 17.4766 33.035C17.3876 32.9706 17.2545 32.8729 17.0835 32.7432C16.7414 32.4838 16.2486 32.0971 15.6553 31.5948C14.4672 30.5889 12.884 29.126 11.3033 27.2999C8.11939 23.6215 5.0625 18.605 5.0625 12.9625H2.9375C2.9375 19.3575 6.38061 24.8597 9.69665 28.6907C11.366 30.6193 13.0328 32.1588 14.2822 33.2166C14.9077 33.7461 15.4305 34.1565 15.7993 34.4363C15.9838 34.5763 16.13 34.6836 16.2314 34.7569C16.2821 34.7936 16.3216 34.8218 16.3492 34.8413C16.363 34.851 16.3738 34.8586 16.3815 34.864C16.3853 34.8667 16.3884 34.8688 16.3907 34.8704C16.3918 34.8712 16.3928 34.8719 16.3935 34.8724C16.3939 34.8727 16.3943 34.873 16.3945 34.8731C16.3949 34.8734 16.3952 34.8736 17 34ZM28.9375 12.9625C28.9375 18.605 25.8806 23.6215 22.6966 27.2999C21.116 29.126 19.5328 30.5889 18.3447 31.5948C17.7514 32.0971 17.2586 32.4838 16.9165 32.7432C16.7455 32.8729 16.6124 32.9706 16.5234 33.035C16.4789 33.0672 16.4454 33.091 16.4238 33.1063C16.413 33.114 16.4051 33.1195 16.4003 33.1229C16.3979 33.1245 16.3963 33.1257 16.3954 33.1263C16.395 33.1266 16.3948 33.1267 16.3947 33.1268C16.3947 33.1268 16.3948 33.1267 16.3948 33.1267C16.395 33.1266 16.3952 33.1264 17 34C17.6048 34.8736 17.6051 34.8734 17.6055 34.8731C17.6057 34.873 17.6061 34.8727 17.6065 34.8724C17.6072 34.8719 17.6082 34.8712 17.6093 34.8704C17.6116 34.8688 17.6147 34.8667 17.6185 34.864C17.6262 34.8586 17.637 34.851 17.6508 34.8413C17.6784 34.8218 17.7179 34.7936 17.7686 34.7569C17.87 34.6836 18.0162 34.5763 18.2007 34.4363C18.5695 34.1565 19.0923 33.7461 19.7178 33.2166C20.9672 32.1588 22.634 30.6193 24.3034 28.6907C27.6194 24.8597 31.0625 19.3575 31.0625 12.9625H28.9375ZM17 23.0625C22.5574 23.0625 27.0625 18.5574 27.0625 13H24.9375C24.9375 17.3838 21.3838 20.9375 17 20.9375V23.0625ZM6.9375 13C6.9375 18.5574 11.4426 23.0625 17 23.0625V20.9375C12.6162 20.9375 9.0625 17.3838 9.0625 13H6.9375ZM17 2.9375C11.4426 2.9375 6.9375 7.44263 6.9375 13H9.0625C9.0625 8.61624 12.6162 5.0625 17 5.0625V2.9375ZM27.0625 13C27.0625 7.44263 22.5574 2.9375 17 2.9375V5.0625C21.3838 5.0625 24.9375 8.61624 24.9375 13H27.0625Z" fill="black" fill-opacity="0.38" mask="url(#path-2-inside-1_8817_262071)"/>
<circle class="marker-icon-background" style="display: none;" cx="17" cy="13" r="9" fill="#fff"></circle>
<g class="marker-icon-container" transform="translate(17,13)">
</g>
<defs>
<filter id="filter0_bf_8817_262071" x="12.75" y="14.75" width="23.9434" height="22.5" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" width="34" height="34" viewBox="0 0 34 34" class="marker-color" fill="#307FE5">
<circle cx="17" cy="17" r="17"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M 17,33 C 25.8366,33 33,25.8366 33,17 33,8.16344 25.8366,1 17,1 8.16344,1 1,8.16344 1,17 1,25.8366 8.16344,33 17,33 Z m 0,1 C 26.3888,34 34,26.3888 34,17 34,7.61116 26.3888,0 17,0 7.61116,0 0,7.61116 0,17 0,26.3888 7.61116,34 17,34 Z"
style="filter:url(#filter2)" />
<g class="marker-icon-container" transform="translate(17,17)" fill="#ffffff">
</g>
<defs>
<filter id="filter2" color-interpolation-filters="sRGB" x="0" y="0" width="1" height="1">
<feColorMatrix id="feColorMatrix2" values="0.60000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.60000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.60000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 " />
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 955 B