62 lines
1.9 KiB
TypeScript
62 lines
1.9 KiB
TypeScript
import { useEffect, type MutableRefObject } from 'react';
|
|
import type maplibregl from 'maplibre-gl';
|
|
import { onMapStyleReady } from '../lib/mapCore';
|
|
import type { MapProjectionId } from '../types';
|
|
|
|
export function useFlyTo(
|
|
mapRef: MutableRefObject<maplibregl.Map | null>,
|
|
projectionRef: MutableRefObject<MapProjectionId>,
|
|
opts: {
|
|
selectedMmsi: number | null;
|
|
shipData: { mmsi: number; lon: number; lat: number }[];
|
|
fleetFocusId: string | number | undefined;
|
|
fleetFocusLon: number | undefined;
|
|
fleetFocusLat: number | undefined;
|
|
fleetFocusZoom: number | undefined;
|
|
},
|
|
) {
|
|
const { selectedMmsi, shipData, fleetFocusId, fleetFocusLon, fleetFocusLat, fleetFocusZoom } = opts;
|
|
|
|
useEffect(() => {
|
|
const map = mapRef.current;
|
|
if (!map) return;
|
|
if (!selectedMmsi) return;
|
|
const t = shipData.find((x) => x.mmsi === selectedMmsi);
|
|
if (!t) return;
|
|
const flyOpts = { center: [t.lon, t.lat] as [number, number], zoom: Math.max(map.getZoom(), 10), duration: 600 };
|
|
if (projectionRef.current === 'globe') {
|
|
map.flyTo(flyOpts);
|
|
} else {
|
|
map.easeTo(flyOpts);
|
|
}
|
|
}, [selectedMmsi, shipData]);
|
|
|
|
useEffect(() => {
|
|
const map = mapRef.current;
|
|
if (!map || fleetFocusLon == null || fleetFocusLat == null || !Number.isFinite(fleetFocusLon) || !Number.isFinite(fleetFocusLat))
|
|
return;
|
|
const lon = fleetFocusLon;
|
|
const lat = fleetFocusLat;
|
|
const zoom = fleetFocusZoom ?? 10;
|
|
|
|
const apply = () => {
|
|
const flyOpts = { center: [lon, lat] as [number, number], zoom, duration: 700 };
|
|
if (projectionRef.current === 'globe') {
|
|
map.flyTo(flyOpts);
|
|
} else {
|
|
map.easeTo(flyOpts);
|
|
}
|
|
};
|
|
|
|
if (map.isStyleLoaded()) {
|
|
apply();
|
|
return;
|
|
}
|
|
|
|
const stop = onMapStyleReady(map, apply);
|
|
return () => {
|
|
stop();
|
|
};
|
|
}, [fleetFocusId, fleetFocusLon, fleetFocusLat, fleetFocusZoom]);
|
|
}
|