Files
gpx.studio/website/src/lib/components/gpx-layer/DistanceMarkers.ts

96 lines
3.5 KiB
TypeScript
Raw Normal View History

2024-05-23 11:21:57 +02:00
2024-06-07 15:54:40 +02:00
import { font } from "$lib/assets/layers";
2024-05-23 11:21:57 +02:00
import { settings } from "$lib/db";
import { gpxStatistics } from "$lib/stores";
import { get } from "svelte/store";
2024-06-07 15:54:40 +02:00
const { distanceMarkers, distanceUnits, currentBasemap } = settings;
2024-05-23 11:21:57 +02:00
export class DistanceMarkers {
map: mapboxgl.Map;
updateBinded: () => void = this.update.bind(this);
2024-07-13 11:42:21 +02:00
unsubscribes: (() => void)[] = [];
2024-05-23 11:21:57 +02:00
constructor(map: mapboxgl.Map) {
this.map = map;
2024-07-13 11:42:21 +02:00
this.unsubscribes.push(gpxStatistics.subscribe(this.updateBinded));
this.unsubscribes.push(distanceMarkers.subscribe(this.updateBinded));
this.unsubscribes.push(distanceUnits.subscribe(this.updateBinded));
2024-06-07 15:54:40 +02:00
this.map.on('style.load', this.updateBinded);
2024-05-23 11:21:57 +02:00
}
update() {
try {
if (get(distanceMarkers)) {
let distanceSource = this.map.getSource('distance-markers');
if (distanceSource) {
distanceSource.setData(this.getDistanceMarkersGeoJSON());
} else {
this.map.addSource('distance-markers', {
type: 'geojson',
data: this.getDistanceMarkersGeoJSON()
});
}
if (!this.map.getLayer('distance-markers')) {
this.map.addLayer({
id: 'distance-markers',
type: 'symbol',
source: 'distance-markers',
layout: {
'text-field': ['get', 'distance'],
2024-06-07 15:54:40 +02:00
'text-size': 14,
'text-font': [font[get(currentBasemap)] ?? 'Open Sans Bold'],
'text-padding': 20,
2024-05-23 11:21:57 +02:00
},
paint: {
2024-06-07 15:54:40 +02:00
'text-color': 'black',
'text-halo-width': 2,
'text-halo-color': 'white',
2024-05-23 11:21:57 +02:00
}
});
} else {
this.map.moveLayer('distance-markers');
}
} else {
if (this.map.getLayer('distance-markers')) {
this.map.removeLayer('distance-markers');
}
}
} catch (e) { // No reliable way to check if the map is ready to add sources and layers
return;
}
}
2024-07-13 11:42:21 +02:00
remove() {
this.unsubscribes.forEach(unsubscribe => unsubscribe());
}
2024-05-23 11:21:57 +02:00
getDistanceMarkersGeoJSON(): GeoJSON.FeatureCollection {
let statistics = get(gpxStatistics);
let features = [];
let currentTargetDistance = 1;
2024-06-11 22:42:03 +02:00
for (let i = 0; i < statistics.local.distance.total.length; i++) {
if (statistics.local.distance.total[i] >= currentTargetDistance * (get(distanceUnits) === 'metric' ? 1 : 1.60934)) {
2024-05-23 11:21:57 +02:00
let distance = currentTargetDistance.toFixed(0);
features.push({
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [statistics.local.points[i].getLongitude(), statistics.local.points[i].getLatitude()]
},
properties: {
distance,
}
} as GeoJSON.Feature);
currentTargetDistance += 1;
}
}
return {
type: 'FeatureCollection',
features
};
}
}