gc-wing/apps/web/src/widgets/map3d/hooks/useFlyTo.ts

62 lines
1.9 KiB
TypeScript
Raw Normal View 히스토리

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]);
}