feat(map): OSM 베이스맵 추가 + 3-way 라디오 그룹 전환 #54

병합
htlee feature/multi-track-select 에서 develop 로 2 commits 를 머지했습니다 2026-03-10 14:41:42 +09:00
6개의 변경된 파일52개의 추가작업 그리고 14개의 파일을 삭제

파일 보기

@ -464,10 +464,10 @@ export function DashboardPage() {
<WeatherOverlayPanel {...weatherOverlay} />
{baseMap === 'ocean' ? (
<OceanMapSettingsPanel value={state.oceanMapSettings} onChange={state.setOceanMapSettings} />
) : (
) : baseMap !== 'osm' ? (
<MapSettingsPanel value={mapStyleSettings} onChange={setMapStyleSettings} />
)}
{baseMap !== 'ocean' && <DepthLegend depthStops={mapStyleSettings.depthStops} />}
) : null}
{baseMap !== 'ocean' && baseMap !== 'osm' && <DepthLegend depthStops={mapStyleSettings.depthStops} />}
<MapLegend />
{selectedLegacyVessel ? (
<VesselInfoPanel vessel={selectedLegacyVessel} allVessels={legacyVesselsAll} onClose={() => setSelectedMmsi(null)} onSelectMmsi={setSelectedMmsi} imo={selectedTarget && selectedTarget.imo > 0 ? selectedTarget.imo : undefined} shipImagePath={selectedTarget?.shipImagePath} shipImageCount={selectedTarget?.shipImageCount} onOpenImageModal={handlePanelOpenImageModal} />

파일 보기

@ -157,10 +157,10 @@ export function DashboardSidebar({
</Section>
<Section
title="지도 표시 설정"
title="지도 설정"
className="md:shrink-0"
actions={
<div className="flex gap-1">
<div className="flex items-center gap-1">
<ToggleButton
on={freeCamera}
onClick={toggleFreeCamera}
@ -169,14 +169,6 @@ export function DashboardSidebar({
>
</ToggleButton>
<ToggleButton
on={baseMap === 'ocean'}
onClick={() => setBaseMap(baseMap === 'ocean' ? 'enhanced' : 'ocean')}
title="Ocean 전용 지도 (해양 정보 극대화)"
className="px-2 py-0.5 text-[9px]"
>
Ocean
</ToggleButton>
<ToggleButton
on={projection === 'globe'}
onClick={isProjectionToggleDisabled ? undefined : () => setProjection((p) => (p === 'globe' ? 'mercator' : 'globe'))}
@ -185,6 +177,31 @@ export function DashboardSidebar({
>
3D
</ToggleButton>
<span className="mx-0.5 h-3 w-px bg-wing-border" />
<ToggleButton
on={baseMap === 'enhanced'}
onClick={() => setBaseMap('enhanced')}
title="기본 지도 (MapTiler Enhanced)"
className="px-2 py-0.5 text-[9px]"
>
Base
</ToggleButton>
<ToggleButton
on={baseMap === 'osm'}
onClick={() => setBaseMap('osm')}
title="OSM 기본 래스터 지도"
className="px-2 py-0.5 text-[9px]"
>
OSM
</ToggleButton>
<ToggleButton
on={baseMap === 'ocean'}
onClick={() => setBaseMap('ocean')}
title="Ocean 전용 지도 (해양 정보 극대화)"
className="px-2 py-0.5 text-[9px]"
>
Ocean
</ToggleButton>
</div>
}
>

파일 보기

@ -63,6 +63,7 @@ export function useBaseMapToggle(
const apply = () => {
if (!map.isStyleLoaded()) return;
if (baseMap === 'osm') return;
const seaVisibility = 'visible' as const;
const seaRegex = /(water|sea|ocean|river|lake|coast|bay)/i;

파일 보기

@ -394,6 +394,23 @@ export async function resolveMapStyle(baseMap: BaseMapId, signal: AbortSignal):
const { resolveOceanStyle } = await import('../../../features/oceanMap/lib/resolveOceanStyle');
return resolveOceanStyle(signal);
}
if (baseMap === 'osm') {
void signal;
return {
version: 8,
name: 'OSM Raster',
glyphs: 'https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf',
sources: {
osm: {
type: 'raster',
tiles: ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'],
tileSize: 256,
attribution: '© OpenStreetMap contributors',
},
},
layers: [{ id: 'osm', type: 'raster', source: 'osm' }],
} satisfies StyleSpecification;
}
// 레거시 베이스맵 비활성 — 향후 위성/라이트 테마 등 추가 시 재활용
// if (baseMap === 'legacy') return '/map/styles/carto-dark.json';
void baseMap;

파일 보기

@ -14,7 +14,7 @@ export type Map3DSettings = {
showDensity: boolean;
};
export type BaseMapId = 'enhanced' | 'ocean' | 'legacy';
export type BaseMapId = 'enhanced' | 'osm' | 'ocean' | 'legacy';
export type MapProjectionId = 'mercator' | 'globe';
export interface MapViewState {

파일 보기

@ -4,5 +4,8 @@
## [Unreleased]
### 추가
- OSM 베이스맵 추가 + Base/OSM/Ocean 3-way 라디오 그룹 전환
### 기타
- 팀 워크플로우 v1.6.1 동기화 + 관리 파일 .gitignore 전환