start/end & distance markers

This commit is contained in:
vcoppe
2025-10-19 14:15:52 +02:00
parent a8d3af35de
commit ba1ac69151
4 changed files with 64 additions and 48 deletions

View File

@@ -1,41 +1,33 @@
<script lang="ts">
import { gpxLayers } from '$lib/components/map/gpx-layer/gpx-layers';
import { onMount } from 'svelte';
import { onDestroy, onMount } from 'svelte';
// import { map, gpxLayers } from '$lib/stores';
// import { GPXLayer } from './gpx-layer';
// import { DistanceMarkers } from './DistanceMarkers';
// import { StartEndMarkers } from './StartEndMarkers';
import { DistanceMarkers } from '$lib/components/map/gpx-layer/distance-markers';
import { StartEndMarkers } from '$lib/components/map/gpx-layer/start-end-markers';
// import { onDestroy } from 'svelte';
// import { createPopups, removePopups } from './GPXLayerPopup';
// let distanceMarkers = $derived(map.current ? new DistanceMarkers(map.current) : undefined);
// let startEndMarkers = $derived(map.current ? new StartEndMarkers(map.current) : undefined);
let distanceMarkers: DistanceMarkers;
let startEndMarkers: StartEndMarkers;
// $: if ($map) {
// if (distanceMarkers) {
// distanceMarkers.remove();
// }
// if (startEndMarkers) {
// startEndMarkers.remove();
// }
// createPopups($map);
// distanceMarkers = new DistanceMarkers($map);
// startEndMarkers = new StartEndMarkers($map);
// }
// onDestroy(() => {
// removePopups();
// if (distanceMarkers) {
// distanceMarkers.remove();
// distanceMarkers = undefined;
// }
// if (startEndMarkers) {
// startEndMarkers.remove();
// startEndMarkers = undefined;
// }
// });
onMount(() => {
gpxLayers.init();
startEndMarkers = new StartEndMarkers();
distanceMarkers = new DistanceMarkers();
});
onDestroy(() => {
// removePopups();
if (startEndMarkers) {
startEndMarkers.remove();
}
if (distanceMarkers) {
distanceMarkers.remove();
}
});
</script>

View File

@@ -1,6 +1,9 @@
import { settings } from '$lib/logic/settings';
import { gpxStatistics } from '$lib/logic/statistics';
import { getConvertedDistanceToKilometers } from '$lib/units';
import type { GeoJSONSource } from 'mapbox-gl';
import { get } from 'svelte/store';
import { map } from '$lib/components/map/map';
const { distanceMarkers, distanceUnits } = settings;
@@ -14,35 +17,40 @@ const stops = [
];
export class DistanceMarkers {
map: mapboxgl.Map;
updateBinded: () => void = this.update.bind(this);
unsubscribes: (() => void)[] = [];
constructor(map: mapboxgl.Map) {
this.map = map;
constructor() {
this.unsubscribes.push(gpxStatistics.subscribe(this.updateBinded));
this.unsubscribes.push(distanceMarkers.subscribe(this.updateBinded));
this.unsubscribes.push(distanceUnits.subscribe(this.updateBinded));
this.map.on('style.import.load', this.updateBinded);
this.unsubscribes.push(
map.subscribe((map_) => {
if (map_) {
map_.on('style.import.load', this.updateBinded);
}
})
);
}
update() {
const map_ = get(map);
if (!map_) return;
try {
if (get(distanceMarkers)) {
let distanceSource: GeoJSONSource | undefined =
this.map.getSource('distance-markers');
let distanceSource: GeoJSONSource | undefined = map_.getSource('distance-markers');
if (distanceSource) {
distanceSource.setData(this.getDistanceMarkersGeoJSON());
} else {
this.map.addSource('distance-markers', {
map_.addSource('distance-markers', {
type: 'geojson',
data: this.getDistanceMarkersGeoJSON(),
});
}
stops.forEach(([d, minzoom, maxzoom]) => {
if (!this.map.getLayer(`distance-markers-${d}`)) {
this.map.addLayer({
if (!map_.getLayer(`distance-markers-${d}`)) {
map_.addLayer({
id: `distance-markers-${d}`,
type: 'symbol',
source: 'distance-markers',
@@ -68,13 +76,13 @@ export class DistanceMarkers {
},
});
} else {
this.map.moveLayer(`distance-markers-${d}`);
map_.moveLayer(`distance-markers-${d}`);
}
});
} else {
stops.forEach(([d]) => {
if (this.map.getLayer(`distance-markers-${d}`)) {
this.map.removeLayer(`distance-markers-${d}`);
if (map_.getLayer(`distance-markers-${d}`)) {
map_.removeLayer(`distance-markers-${d}`);
}
});
}
@@ -96,7 +104,7 @@ export class DistanceMarkers {
for (let i = 0; i < statistics.local.distance.total.length; i++) {
if (
statistics.local.distance.total[i] >=
currentTargetDistance * (get(distanceUnits) === 'metric' ? 1 : 1.60934)
getConvertedDistanceToKilometers(currentTargetDistance)
) {
let distance = currentTargetDistance.toFixed(0);
let [level, minzoom] = stops.find(([d]) => currentTargetDistance % d === 0) ?? [

View File

@@ -1,17 +1,16 @@
import { gpxStatistics, slicedGPXStatistics, currentTool, Tool } from '$lib/stores';
import { currentTool, Tool } from '$lib/components/toolbar/tools';
import { gpxStatistics, slicedGPXStatistics } from '$lib/logic/statistics';
import mapboxgl from 'mapbox-gl';
import { get } from 'svelte/store';
import { map } from '$lib/components/map/map';
export class StartEndMarkers {
map: mapboxgl.Map;
start: mapboxgl.Marker;
end: mapboxgl.Marker;
updateBinded: () => void = this.update.bind(this);
unsubscribes: (() => void)[] = [];
constructor(map: mapboxgl.Map) {
this.map = map;
constructor() {
let startElement = document.createElement('div');
let endElement = document.createElement('div');
startElement.className = `h-4 w-4 rounded-full bg-green-500 border-2 border-white`;
@@ -28,15 +27,18 @@ export class StartEndMarkers {
}
update() {
let tool = get(currentTool);
let statistics = get(slicedGPXStatistics)?.[0] ?? get(gpxStatistics);
const map_ = get(map);
if (!map_) return;
const tool = get(currentTool);
const statistics = get(slicedGPXStatistics)?.[0] ?? get(gpxStatistics);
if (statistics.local.points.length > 0 && tool !== Tool.ROUTING) {
this.start.setLngLat(statistics.local.points[0].getCoordinates()).addTo(this.map);
this.start.setLngLat(statistics.local.points[0].getCoordinates()).addTo(map_);
this.end
.setLngLat(
statistics.local.points[statistics.local.points.length - 1].getCoordinates()
)
.addTo(this.map);
.addTo(map_);
} else {
this.start.remove();
this.end.remove();

View File

@@ -178,6 +178,20 @@ export function getConvertedDistance(value: number, targetDistanceUnits = get(di
}
}
export function getConvertedDistanceToKilometers(
value: number,
sourceDistanceUnits = get(distanceUnits)
) {
switch (sourceDistanceUnits) {
case 'metric':
return value;
case 'imperial':
return milesToKilometers(value);
case 'nautical':
return nauticalMilesToKilometers(value);
}
}
export function getConvertedElevation(value: number, targetDistanceUnits = get(distanceUnits)) {
switch (targetDistanceUnits) {
case 'metric':