- 배경지도 타입 전환 (일반/전자해도/야간) - 테마 연동 색상 시스템 (선박 라벨, 속도벡터 등) - mapStore에 subscribeWithSelector 적용 - 신호원 우선순위/항적 조회기간 상수 추가 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
123 lines
2.8 KiB
JavaScript
123 lines
2.8 KiB
JavaScript
import { create } from 'zustand';
|
|
import { subscribeWithSelector } from 'zustand/middleware';
|
|
|
|
/**
|
|
* 배경지도 타입
|
|
* - normal: 일반지도
|
|
* - enc: 전자해도
|
|
* - dark: 야간지도
|
|
*/
|
|
export const BASE_MAP_TYPES = {
|
|
NORMAL: 'normal',
|
|
ENC: 'enc',
|
|
DARK: 'dark',
|
|
};
|
|
|
|
/**
|
|
* 테마 타입 (배경지도에 연동)
|
|
* - light: 일반지도, 전자해도
|
|
* - dark: 야간지도
|
|
*/
|
|
export const THEME_TYPES = {
|
|
LIGHT: 'light',
|
|
DARK: 'dark',
|
|
};
|
|
|
|
/**
|
|
* 배경지도 -> 테마 매핑
|
|
*/
|
|
const BASE_MAP_TO_THEME = {
|
|
[BASE_MAP_TYPES.NORMAL]: THEME_TYPES.LIGHT,
|
|
[BASE_MAP_TYPES.ENC]: THEME_TYPES.LIGHT,
|
|
[BASE_MAP_TYPES.DARK]: THEME_TYPES.DARK,
|
|
};
|
|
|
|
/**
|
|
* 테마별 색상 정의
|
|
* - 선박 레이어에서 사용
|
|
*/
|
|
export const THEME_COLORS = {
|
|
[THEME_TYPES.LIGHT]: {
|
|
shipLabel: [30, 30, 30, 255],
|
|
shipLabelOutline: [255, 255, 255, 255],
|
|
speedVector: [0, 0, 0, 200],
|
|
shipDim: [0, 100, 200, 180],
|
|
},
|
|
[THEME_TYPES.DARK]: {
|
|
shipLabel: [255, 255, 255, 255],
|
|
shipLabelOutline: [30, 30, 30, 255],
|
|
speedVector: [255, 255, 255, 200],
|
|
shipDim: [100, 200, 255, 180],
|
|
},
|
|
};
|
|
|
|
/**
|
|
* 지도 상태 관리 스토어
|
|
*/
|
|
export const useMapStore = create(subscribeWithSelector((set, get) => ({
|
|
// 지도 인스턴스
|
|
map: null,
|
|
setMap: (map) => set({ map }),
|
|
|
|
// 배경지도 타입 (기본: 야간지도)
|
|
baseMapType: BASE_MAP_TYPES.DARK,
|
|
setBaseMapType: (type) => set({ baseMapType: type }),
|
|
|
|
// 현재 테마 (배경지도에 연동)
|
|
getTheme: () => BASE_MAP_TO_THEME[get().baseMapType] || THEME_TYPES.LIGHT,
|
|
|
|
// 현재 테마 색상 가져오기
|
|
getThemeColors: () => THEME_COLORS[get().getTheme()],
|
|
|
|
// 줌 레벨
|
|
zoom: 7,
|
|
setZoom: (zoom) => set({ zoom }),
|
|
|
|
zoomIn: () => {
|
|
const { map, zoom } = get();
|
|
if (map && zoom < 17) {
|
|
const newZoom = zoom + 1;
|
|
map.getView().setZoom(newZoom);
|
|
set({ zoom: newZoom });
|
|
}
|
|
},
|
|
|
|
zoomOut: () => {
|
|
const { map, zoom } = get();
|
|
if (map && zoom > 0) {
|
|
const newZoom = zoom - 1;
|
|
map.getView().setZoom(newZoom);
|
|
set({ zoom: newZoom });
|
|
}
|
|
},
|
|
|
|
// 중심 좌표 [lon, lat]
|
|
center: [127.1388684, 37.4449168],
|
|
setCenter: (center) => set({ center }),
|
|
|
|
// 측정 도구
|
|
activeMeasureTool: null,
|
|
areaShape: null,
|
|
|
|
setMeasureTool: (tool) => set((state) => ({
|
|
activeMeasureTool: state.activeMeasureTool === tool ? null : tool,
|
|
areaShape: null,
|
|
})),
|
|
setAreaShape: (shape) => set({ areaShape: shape }),
|
|
clearMeasure: () => set({ activeMeasureTool: null, areaShape: null }),
|
|
|
|
// 레이어 가시성
|
|
layerVisibility: {
|
|
baseMap: true,
|
|
ships: true,
|
|
weather: false,
|
|
satellite: false,
|
|
},
|
|
toggleLayer: (layerName) => set((state) => ({
|
|
layerVisibility: {
|
|
...state.layerVisibility,
|
|
[layerName]: !state.layerVisibility[layerName],
|
|
},
|
|
})),
|
|
})));
|