Files
gpx.studio/website/src/lib/components/map/map-popup.ts

85 lines
2.4 KiB
TypeScript
Raw Normal View History

2025-10-17 23:54:45 +02:00
import { TrackPoint, Waypoint } from 'gpx';
2026-01-30 21:01:24 +01:00
import maplibregl from 'maplibre-gl';
2025-11-09 18:03:27 +01:00
import { mount, tick, unmount } from 'svelte';
2025-10-17 23:54:45 +02:00
import { get, writable, type Writable } from 'svelte/store';
import MapPopupComponent from '$lib/components/map/MapPopup.svelte';
export type PopupItem<T = Waypoint | TrackPoint | any> = {
item: T;
fileId?: string;
hide?: () => void;
};
export class MapPopup {
2026-01-30 21:01:24 +01:00
map: maplibregl.Map;
popup: maplibregl.Popup;
2025-10-17 23:54:45 +02:00
item: Writable<PopupItem | null> = writable(null);
component: ReturnType<typeof mount>;
maybeHideBinded = this.maybeHide.bind(this);
2026-01-30 21:01:24 +01:00
constructor(map: maplibregl.Map, options?: maplibregl.PopupOptions) {
2025-10-17 23:54:45 +02:00
this.map = map;
2026-01-30 21:01:24 +01:00
this.popup = new maplibregl.Popup(options);
2025-10-17 23:54:45 +02:00
this.component = mount(MapPopupComponent, {
target: document.body,
props: {
item: this.item,
onContainerReady: (container: HTMLDivElement) => {
this.popup.setDOMContent(container);
},
},
});
}
setItem(item: PopupItem | null) {
if (item) item.hide = () => this.hide();
this.item.set(item);
if (item === null) {
this.hide();
} else {
tick().then(() => this.show());
}
}
show() {
const item = get(this.item);
if (item === null) {
this.hide();
return;
}
this.popup.setLngLat(this.getCoordinates()).addTo(this.map);
this.map.on('mousemove', this.maybeHideBinded);
}
2026-01-30 21:01:24 +01:00
maybeHide(e: maplibregl.MapMouseEvent) {
2025-10-17 23:54:45 +02:00
const item = get(this.item);
if (item === null) {
this.hide();
return;
}
if (this.map.project(this.getCoordinates()).dist(this.map.project(e.lngLat)) > 60) {
this.hide();
}
}
hide() {
this.popup.remove();
this.map.off('mousemove', this.maybeHideBinded);
}
remove() {
this.popup.remove();
2025-11-09 18:03:27 +01:00
unmount(this.component);
2025-10-17 23:54:45 +02:00
}
getCoordinates() {
const item = get(this.item);
if (item === null) {
2026-01-30 21:01:24 +01:00
return new maplibregl.LngLat(0, 0);
2025-10-17 23:54:45 +02:00
}
return item.item instanceof Waypoint || item.item instanceof TrackPoint
? item.item.getCoordinates()
2026-01-30 21:01:24 +01:00
: new maplibregl.LngLat(item.item.lon, item.item.lat);
2025-10-17 23:54:45 +02:00
}
}