mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2025-11-04 21:41:07 +00:00
start/end & distance markers
This commit is contained in:
@@ -1,41 +1,33 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { gpxLayers } from '$lib/components/map/gpx-layer/gpx-layers';
|
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 { map, gpxLayers } from '$lib/stores';
|
||||||
// import { GPXLayer } from './gpx-layer';
|
// import { GPXLayer } from './gpx-layer';
|
||||||
// import { DistanceMarkers } from './DistanceMarkers';
|
import { DistanceMarkers } from '$lib/components/map/gpx-layer/distance-markers';
|
||||||
// import { StartEndMarkers } from './StartEndMarkers';
|
import { StartEndMarkers } from '$lib/components/map/gpx-layer/start-end-markers';
|
||||||
// import { onDestroy } from 'svelte';
|
// import { onDestroy } from 'svelte';
|
||||||
// import { createPopups, removePopups } from './GPXLayerPopup';
|
// import { createPopups, removePopups } from './GPXLayerPopup';
|
||||||
|
|
||||||
// let distanceMarkers = $derived(map.current ? new DistanceMarkers(map.current) : undefined);
|
let distanceMarkers: DistanceMarkers;
|
||||||
// let startEndMarkers = $derived(map.current ? new StartEndMarkers(map.current) : undefined);
|
let startEndMarkers: StartEndMarkers;
|
||||||
|
|
||||||
// $: if ($map) {
|
// $: if ($map) {
|
||||||
// if (distanceMarkers) {
|
|
||||||
// distanceMarkers.remove();
|
|
||||||
// }
|
|
||||||
// if (startEndMarkers) {
|
|
||||||
// startEndMarkers.remove();
|
|
||||||
// }
|
|
||||||
// createPopups($map);
|
// 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(() => {
|
onMount(() => {
|
||||||
gpxLayers.init();
|
gpxLayers.init();
|
||||||
|
startEndMarkers = new StartEndMarkers();
|
||||||
|
distanceMarkers = new DistanceMarkers();
|
||||||
|
});
|
||||||
|
|
||||||
|
onDestroy(() => {
|
||||||
|
// removePopups();
|
||||||
|
if (startEndMarkers) {
|
||||||
|
startEndMarkers.remove();
|
||||||
|
}
|
||||||
|
if (distanceMarkers) {
|
||||||
|
distanceMarkers.remove();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import { settings } from '$lib/logic/settings';
|
import { settings } from '$lib/logic/settings';
|
||||||
|
import { gpxStatistics } from '$lib/logic/statistics';
|
||||||
|
import { getConvertedDistanceToKilometers } from '$lib/units';
|
||||||
import type { GeoJSONSource } from 'mapbox-gl';
|
import type { GeoJSONSource } from 'mapbox-gl';
|
||||||
import { get } from 'svelte/store';
|
import { get } from 'svelte/store';
|
||||||
|
import { map } from '$lib/components/map/map';
|
||||||
|
|
||||||
const { distanceMarkers, distanceUnits } = settings;
|
const { distanceMarkers, distanceUnits } = settings;
|
||||||
|
|
||||||
@@ -14,35 +17,40 @@ const stops = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export class DistanceMarkers {
|
export class DistanceMarkers {
|
||||||
map: mapboxgl.Map;
|
|
||||||
updateBinded: () => void = this.update.bind(this);
|
updateBinded: () => void = this.update.bind(this);
|
||||||
unsubscribes: (() => void)[] = [];
|
unsubscribes: (() => void)[] = [];
|
||||||
|
|
||||||
constructor(map: mapboxgl.Map) {
|
constructor() {
|
||||||
this.map = map;
|
|
||||||
|
|
||||||
this.unsubscribes.push(gpxStatistics.subscribe(this.updateBinded));
|
this.unsubscribes.push(gpxStatistics.subscribe(this.updateBinded));
|
||||||
this.unsubscribes.push(distanceMarkers.subscribe(this.updateBinded));
|
this.unsubscribes.push(distanceMarkers.subscribe(this.updateBinded));
|
||||||
this.unsubscribes.push(distanceUnits.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() {
|
update() {
|
||||||
|
const map_ = get(map);
|
||||||
|
if (!map_) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (get(distanceMarkers)) {
|
if (get(distanceMarkers)) {
|
||||||
let distanceSource: GeoJSONSource | undefined =
|
let distanceSource: GeoJSONSource | undefined = map_.getSource('distance-markers');
|
||||||
this.map.getSource('distance-markers');
|
|
||||||
if (distanceSource) {
|
if (distanceSource) {
|
||||||
distanceSource.setData(this.getDistanceMarkersGeoJSON());
|
distanceSource.setData(this.getDistanceMarkersGeoJSON());
|
||||||
} else {
|
} else {
|
||||||
this.map.addSource('distance-markers', {
|
map_.addSource('distance-markers', {
|
||||||
type: 'geojson',
|
type: 'geojson',
|
||||||
data: this.getDistanceMarkersGeoJSON(),
|
data: this.getDistanceMarkersGeoJSON(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
stops.forEach(([d, minzoom, maxzoom]) => {
|
stops.forEach(([d, minzoom, maxzoom]) => {
|
||||||
if (!this.map.getLayer(`distance-markers-${d}`)) {
|
if (!map_.getLayer(`distance-markers-${d}`)) {
|
||||||
this.map.addLayer({
|
map_.addLayer({
|
||||||
id: `distance-markers-${d}`,
|
id: `distance-markers-${d}`,
|
||||||
type: 'symbol',
|
type: 'symbol',
|
||||||
source: 'distance-markers',
|
source: 'distance-markers',
|
||||||
@@ -68,13 +76,13 @@ export class DistanceMarkers {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.map.moveLayer(`distance-markers-${d}`);
|
map_.moveLayer(`distance-markers-${d}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
stops.forEach(([d]) => {
|
stops.forEach(([d]) => {
|
||||||
if (this.map.getLayer(`distance-markers-${d}`)) {
|
if (map_.getLayer(`distance-markers-${d}`)) {
|
||||||
this.map.removeLayer(`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++) {
|
for (let i = 0; i < statistics.local.distance.total.length; i++) {
|
||||||
if (
|
if (
|
||||||
statistics.local.distance.total[i] >=
|
statistics.local.distance.total[i] >=
|
||||||
currentTargetDistance * (get(distanceUnits) === 'metric' ? 1 : 1.60934)
|
getConvertedDistanceToKilometers(currentTargetDistance)
|
||||||
) {
|
) {
|
||||||
let distance = currentTargetDistance.toFixed(0);
|
let distance = currentTargetDistance.toFixed(0);
|
||||||
let [level, minzoom] = stops.find(([d]) => currentTargetDistance % d === 0) ?? [
|
let [level, minzoom] = stops.find(([d]) => currentTargetDistance % d === 0) ?? [
|
||||||
@@ -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 mapboxgl from 'mapbox-gl';
|
||||||
import { get } from 'svelte/store';
|
import { get } from 'svelte/store';
|
||||||
|
import { map } from '$lib/components/map/map';
|
||||||
|
|
||||||
export class StartEndMarkers {
|
export class StartEndMarkers {
|
||||||
map: mapboxgl.Map;
|
|
||||||
start: mapboxgl.Marker;
|
start: mapboxgl.Marker;
|
||||||
end: mapboxgl.Marker;
|
end: mapboxgl.Marker;
|
||||||
updateBinded: () => void = this.update.bind(this);
|
updateBinded: () => void = this.update.bind(this);
|
||||||
unsubscribes: (() => void)[] = [];
|
unsubscribes: (() => void)[] = [];
|
||||||
|
|
||||||
constructor(map: mapboxgl.Map) {
|
constructor() {
|
||||||
this.map = map;
|
|
||||||
|
|
||||||
let startElement = document.createElement('div');
|
let startElement = document.createElement('div');
|
||||||
let endElement = document.createElement('div');
|
let endElement = document.createElement('div');
|
||||||
startElement.className = `h-4 w-4 rounded-full bg-green-500 border-2 border-white`;
|
startElement.className = `h-4 w-4 rounded-full bg-green-500 border-2 border-white`;
|
||||||
@@ -28,15 +27,18 @@ export class StartEndMarkers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
update() {
|
||||||
let tool = get(currentTool);
|
const map_ = get(map);
|
||||||
let statistics = get(slicedGPXStatistics)?.[0] ?? get(gpxStatistics);
|
if (!map_) return;
|
||||||
|
|
||||||
|
const tool = get(currentTool);
|
||||||
|
const statistics = get(slicedGPXStatistics)?.[0] ?? get(gpxStatistics);
|
||||||
if (statistics.local.points.length > 0 && tool !== Tool.ROUTING) {
|
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
|
this.end
|
||||||
.setLngLat(
|
.setLngLat(
|
||||||
statistics.local.points[statistics.local.points.length - 1].getCoordinates()
|
statistics.local.points[statistics.local.points.length - 1].getCoordinates()
|
||||||
)
|
)
|
||||||
.addTo(this.map);
|
.addTo(map_);
|
||||||
} else {
|
} else {
|
||||||
this.start.remove();
|
this.start.remove();
|
||||||
this.end.remove();
|
this.end.remove();
|
||||||
@@ -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)) {
|
export function getConvertedElevation(value: number, targetDistanceUnits = get(distanceUnits)) {
|
||||||
switch (targetDistanceUnits) {
|
switch (targetDistanceUnits) {
|
||||||
case 'metric':
|
case 'metric':
|
||||||
|
|||||||
Reference in New Issue
Block a user