fix(map): 패널 선택 fly-to 즉시 반응 개선
- shipData를 ref로 관리하여 AIS poll마다 effect 재실행 방지 - isStyleLoaded 가드 제거 → try/catch로 즉시 실행 - duration 700→400ms로 단축 - selectedMmsi만 의존성으로 → 선택 시 1회만 fly-to 실행 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
부모
f9da13b694
커밋
59a5e6beac
@ -1,6 +1,5 @@
|
||||
import { useEffect, type MutableRefObject } from 'react';
|
||||
import { useEffect, useRef, type MutableRefObject } from 'react';
|
||||
import type maplibregl from 'maplibre-gl';
|
||||
import { onMapStyleReady } from '../lib/mapCore';
|
||||
import type { MapProjectionId } from '../types';
|
||||
|
||||
export function useFlyTo(
|
||||
@ -19,7 +18,11 @@ export function useFlyTo(
|
||||
) {
|
||||
const { selectedMmsi, shipData, mapInitiatedSelectRef, fleetFocusId, fleetFocusLon, fleetFocusLat, fleetFocusZoom } = opts;
|
||||
|
||||
// 패널(좌측 목록)에서 선택 시 해당 선박 위치로 이동
|
||||
// shipData를 ref로 — 의존성에서 제외하여 AIS poll마다 재실행 방지
|
||||
const shipDataRef = useRef(shipData);
|
||||
useEffect(() => { shipDataRef.current = shipData; }, [shipData]);
|
||||
|
||||
// 패널(좌측 목록)에서 선택 시 해당 선박 위치로 즉시 이동
|
||||
useEffect(() => {
|
||||
// 지도 내부 클릭에서 발생한 선택이면 스킵
|
||||
if (mapInitiatedSelectRef.current) {
|
||||
@ -30,53 +33,37 @@ export function useFlyTo(
|
||||
const map = mapRef.current;
|
||||
if (!map || selectedMmsi == null) return;
|
||||
|
||||
const target = shipData.find((t) => t.mmsi === selectedMmsi);
|
||||
const target = shipDataRef.current.find((t) => t.mmsi === selectedMmsi);
|
||||
if (!target || !Number.isFinite(target.lon) || !Number.isFinite(target.lat)) return;
|
||||
|
||||
const apply = () => {
|
||||
const flyOpts = { center: [target.lon, target.lat] as [number, number], duration: 700 };
|
||||
try {
|
||||
const flyOpts = { center: [target.lon, target.lat] as [number, number], duration: 400 };
|
||||
if (projectionRef.current === 'globe') {
|
||||
map.flyTo(flyOpts);
|
||||
} else {
|
||||
map.easeTo(flyOpts);
|
||||
}
|
||||
};
|
||||
|
||||
if (map.isStyleLoaded()) {
|
||||
apply();
|
||||
return;
|
||||
} catch {
|
||||
// ignore — style not ready 등
|
||||
}
|
||||
|
||||
const stop = onMapStyleReady(map, apply);
|
||||
return () => { stop(); };
|
||||
}, [selectedMmsi, shipData]);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [selectedMmsi]);
|
||||
|
||||
// 선단 포커스 이동
|
||||
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 };
|
||||
try {
|
||||
const flyOpts = { center: [fleetFocusLon, fleetFocusLat] as [number, number], zoom: fleetFocusZoom ?? 10, duration: 500 };
|
||||
if (projectionRef.current === 'globe') {
|
||||
map.flyTo(flyOpts);
|
||||
} else {
|
||||
map.easeTo(flyOpts);
|
||||
}
|
||||
};
|
||||
|
||||
if (map.isStyleLoaded()) {
|
||||
apply();
|
||||
return;
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
|
||||
const stop = onMapStyleReady(map, apply);
|
||||
return () => {
|
||||
stop();
|
||||
};
|
||||
}, [fleetFocusId, fleetFocusLon, fleetFocusLat, fleetFocusZoom]);
|
||||
}
|
||||
|
||||
불러오는 중...
Reference in New Issue
Block a user