- 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>
65 lines
2.0 KiB
TypeScript
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]);
|
|
}
|