import { currentTool, Tool } from '$lib/components/toolbar/tools'; import { gpxStatistics, hoveredPoint, slicedGPXStatistics } from '$lib/logic/statistics'; import type { GeoJSONSource } from 'maplibre-gl'; import { get } from 'svelte/store'; import { map } from '$lib/components/map/map'; import { allHidden } from '$lib/logic/hidden'; import { ANCHOR_LAYER_KEY } from '$lib/components/map/style'; import { loadSVGIcon } from '$lib/utils'; const startMarkerSVG = ` `; const endMarkerSVG = ` `; const hoverMarkerSVG = ` `; export class StartEndMarkers { updateBinded: () => void = this.update.bind(this); unsubscribes: (() => void)[] = []; constructor() { map.onLoad(() => this.update()); this.unsubscribes.push(gpxStatistics.subscribe(this.updateBinded)); this.unsubscribes.push(slicedGPXStatistics.subscribe(this.updateBinded)); this.unsubscribes.push(hoveredPoint.subscribe(this.updateBinded)); this.unsubscribes.push(currentTool.subscribe(this.updateBinded)); this.unsubscribes.push(allHidden.subscribe(this.updateBinded)); } update() { const map_ = get(map); if (!map_) return; this.loadIcons(); const tool = get(currentTool); const statistics = get(gpxStatistics); const slicedStatistics = get(slicedGPXStatistics); const hovered = get(hoveredPoint); const hidden = get(allHidden); if (!hidden) { const data: GeoJSON.FeatureCollection = { type: 'FeatureCollection', features: [], }; if (statistics.global.length > 0 && tool !== Tool.ROUTING) { const start = statistics .getTrackPoint(slicedStatistics?.[1] ?? 0)! .trkpt.getCoordinates(); const end = statistics .getTrackPoint(slicedStatistics?.[2] ?? statistics.global.length - 1)! .trkpt.getCoordinates(); data.features.push({ type: 'Feature', geometry: { type: 'Point', coordinates: [start.lon, start.lat], }, properties: { icon: 'start-marker', }, }); data.features.push({ type: 'Feature', geometry: { type: 'Point', coordinates: [end.lon, end.lat], }, properties: { icon: 'end-marker', }, }); } if (hovered) { data.features.push({ type: 'Feature', geometry: { type: 'Point', coordinates: [hovered.lon, hovered.lat], }, properties: { icon: 'hover-marker', }, }); } let source = map_.getSource('start-end-markers') as GeoJSONSource | undefined; if (source) { source.setData(data); } else { map_.addSource('start-end-markers', { type: 'geojson', data: data, }); } if (!map_.getLayer('start-end-markers')) { map_.addLayer( { id: 'start-end-markers', type: 'symbol', source: 'start-end-markers', layout: { 'icon-image': ['get', 'icon'], 'icon-size': 0.2, 'icon-allow-overlap': true, }, }, ANCHOR_LAYER_KEY.startEndMarkers ); } } else { if (map_.getLayer('start-end-markers')) { map_.removeLayer('start-end-markers'); } if (map_.getSource('start-end-markers')) { map_.removeSource('start-end-markers'); } } } remove() { this.unsubscribes.forEach((unsubscribe) => unsubscribe()); const map_ = get(map); if (!map_) return; if (map_.getLayer('start-end-markers')) { map_.removeLayer('start-end-markers'); } if (map_.getSource('start-end-markers')) { map_.removeSource('start-end-markers'); } } loadIcons() { const map_ = get(map); if (!map_) return; loadSVGIcon(map_, 'start-marker', startMarkerSVG); loadSVGIcon(map_, 'end-marker', endMarkerSVG); loadSVGIcon(map_, 'hover-marker', hoverMarkerSVG); } }