kcg-monitoring/frontend/src/features/encMap/useEncMapSettings.ts
htlee 650c027013 feat: 한국 현황 위성지도/ENC 토글 + ENC 스타일 설정
- ENC 전자해도: gcnautical 벡터 타일 연동 (gc-wing-dev 이식)
- 상단 위성/ENC 토글 버튼 + ⚙ 드롭다운 설정 패널
- 12개 심볼 토글 + 8개 색상 수정 + 초기화
- mapMode/encSettings localStorage 영속화
- style.load 대기 패턴으로 스타일 전환 시 설정 자동 적용

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 14:08:41 +09:00

65 lines
2.0 KiB
TypeScript

import { useEffect, useRef, type MutableRefObject } from 'react';
import type maplibregl from 'maplibre-gl';
import { applyEncVisibility, applyEncColors } from './encSettings';
import type { EncMapSettings } from './types';
/**
* 스타일 로드 완료를 안정적으로 감지하여 callback 실행.
* gc-wing-dev onMapStyleReady 패턴 이식.
*/
function onStyleReady(map: maplibregl.Map, callback: () => void): () => void {
if (map.isStyleLoaded()) {
callback();
return () => {};
}
let fired = false;
const runOnce = () => {
if (fired || !map.isStyleLoaded()) return;
fired = true;
callback();
try { map.off('style.load', runOnce); map.off('styledata', runOnce); } catch { /* ignore */ }
};
map.on('style.load', runOnce);
map.on('styledata', runOnce);
return () => {
try { map.off('style.load', runOnce); map.off('styledata', runOnce); } catch { /* ignore */ }
};
}
export function useEncMapSettings(
mapRef: MutableRefObject<maplibregl.Map | null>,
mapMode: 'satellite' | 'enc',
settings: EncMapSettings,
syncEpoch = 0,
) {
// settings를 ref로 유지 — style.load 콜백에서 최신값 참조
const settingsRef = useRef(settings);
settingsRef.current = settings;
// syncEpoch 변경 = 맵 로드 완료 → 전체 설정 재적용
// mapMode 변경 = 위성↔ENC 전환 → style.load 대기 후 적용
useEffect(() => {
if (mapMode !== 'enc') return;
const map = mapRef.current;
if (!map) return;
const applyAll = () => {
const s = settingsRef.current;
applyEncVisibility(map, s);
applyEncColors(map, s);
};
const stop = onStyleReady(map, applyAll);
return stop;
}, [mapMode, syncEpoch, mapRef]);
// settings 변경 시 즉시 적용 (스타일이 이미 로드된 상태에서)
useEffect(() => {
if (mapMode !== 'enc') return;
const map = mapRef.current;
if (!map || !map.isStyleLoaded()) return;
applyEncVisibility(map, settings);
applyEncColors(map, settings);
}, [settings, mapMode, mapRef]);
}