refactor(map): lightMode prop 제거, useThemeStore 기반 테마 전환으로 통합
This commit is contained in:
부모
77d36ec8d0
커밋
7921bfef96
@ -1,10 +1,10 @@
|
|||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
import { useMap } from '@vis.gl/react-maplibre';
|
import { useMap } from '@vis.gl/react-maplibre';
|
||||||
import type { HydrDataStep } from '@tabs/prediction/services/predictionApi';
|
import type { HydrDataStep } from '@tabs/prediction/services/predictionApi';
|
||||||
|
import { useThemeStore } from '@common/store/themeStore';
|
||||||
|
|
||||||
interface HydrParticleOverlayProps {
|
interface HydrParticleOverlayProps {
|
||||||
hydrStep: HydrDataStep | null;
|
hydrStep: HydrDataStep | null;
|
||||||
lightMode?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const PARTICLE_COUNT = 3000;
|
const PARTICLE_COUNT = 3000;
|
||||||
@ -27,8 +27,8 @@ interface Particle {
|
|||||||
|
|
||||||
export default function HydrParticleOverlay({
|
export default function HydrParticleOverlay({
|
||||||
hydrStep,
|
hydrStep,
|
||||||
lightMode = false,
|
|
||||||
}: HydrParticleOverlayProps) {
|
}: HydrParticleOverlayProps) {
|
||||||
|
const lightMode = useThemeStore((s) => s.theme) === 'light';
|
||||||
const { current: map } = useMap();
|
const { current: map } = useMap();
|
||||||
const animRef = useRef<number>();
|
const animRef = useRef<number>();
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,7 @@ import { useMeasureTool } from '@common/hooks/useMeasureTool'
|
|||||||
import { hexToRgba } from './mapUtils'
|
import { hexToRgba } from './mapUtils'
|
||||||
import { S57EncOverlay } from './S57EncOverlay'
|
import { S57EncOverlay } from './S57EncOverlay'
|
||||||
import { useMapStore } from '@common/store/mapStore'
|
import { useMapStore } from '@common/store/mapStore'
|
||||||
|
import { useThemeStore } from '@common/store/themeStore'
|
||||||
import { useBaseMapStyle } from '@common/hooks/useBaseMapStyle'
|
import { useBaseMapStyle } from '@common/hooks/useBaseMapStyle'
|
||||||
|
|
||||||
const GEOSERVER_URL = import.meta.env.VITE_GEOSERVER_URL || 'http://localhost:8080'
|
const GEOSERVER_URL = import.meta.env.VITE_GEOSERVER_URL || 'http://localhost:8080'
|
||||||
@ -142,8 +143,6 @@ interface MapViewProps {
|
|||||||
analysisPolygonPoints?: Array<{ lat: number; lon: number }>
|
analysisPolygonPoints?: Array<{ lat: number; lon: number }>
|
||||||
analysisCircleCenter?: { lat: number; lon: number } | null
|
analysisCircleCenter?: { lat: number; lon: number } | null
|
||||||
analysisCircleRadiusM?: number
|
analysisCircleRadiusM?: number
|
||||||
/** 밝은 톤 지도 스타일 사용 (CartoDB Positron) */
|
|
||||||
lightMode?: boolean
|
|
||||||
/** false로 설정 시 WeatherInfoPanel, MapLegend, CoordinateDisplay 숨김 (기본: true) */
|
/** false로 설정 시 WeatherInfoPanel, MapLegend, CoordinateDisplay 숨김 (기본: true) */
|
||||||
showOverlays?: boolean
|
showOverlays?: boolean
|
||||||
}
|
}
|
||||||
@ -328,9 +327,9 @@ export function MapView({
|
|||||||
analysisPolygonPoints = [],
|
analysisPolygonPoints = [],
|
||||||
analysisCircleCenter,
|
analysisCircleCenter,
|
||||||
analysisCircleRadiusM = 0,
|
analysisCircleRadiusM = 0,
|
||||||
lightMode = false,
|
|
||||||
showOverlays = true,
|
showOverlays = true,
|
||||||
}: MapViewProps) {
|
}: MapViewProps) {
|
||||||
|
const lightMode = useThemeStore((s) => s.theme) === 'light'
|
||||||
const { mapToggles, measureMode, measureInProgress, measurements } = useMapStore()
|
const { mapToggles, measureMode, measureInProgress, measurements } = useMapStore()
|
||||||
const { handleMeasureClick } = useMeasureTool()
|
const { handleMeasureClick } = useMeasureTool()
|
||||||
const isControlled = externalCurrentTime !== undefined
|
const isControlled = externalCurrentTime !== undefined
|
||||||
@ -1102,8 +1101,8 @@ export function MapView({
|
|||||||
analysisPolygonPoints, analysisCircleCenter, analysisCircleRadiusM, lightMode,
|
analysisPolygonPoints, analysisCircleCenter, analysisCircleRadiusM, lightMode,
|
||||||
])
|
])
|
||||||
|
|
||||||
// 3D 모드 / 밝은 톤에 따른 지도 스타일 전환
|
// 3D 모드 / 테마에 따른 지도 스타일 전환
|
||||||
const currentMapStyle = useBaseMapStyle(lightMode)
|
const currentMapStyle = useBaseMapStyle()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full h-full relative">
|
<div className="w-full h-full relative">
|
||||||
@ -1164,7 +1163,7 @@ export function MapView({
|
|||||||
|
|
||||||
{/* 해류 파티클 오버레이 */}
|
{/* 해류 파티클 오버레이 */}
|
||||||
{hydrData.length > 0 && showCurrent && (
|
{hydrData.length > 0 && showCurrent && (
|
||||||
<HydrParticleOverlay hydrStep={hydrData[currentTime] ?? null} lightMode={lightMode} />
|
<HydrParticleOverlay hydrStep={hydrData[currentTime] ?? null} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* 사고 위치 마커 (MapLibre Marker) */}
|
{/* 사고 위치 마커 (MapLibre Marker) */}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import type { StyleSpecification } from 'maplibre-gl';
|
import type { StyleSpecification } from 'maplibre-gl';
|
||||||
import { useMapStore } from '@common/store/mapStore';
|
import { useMapStore } from '@common/store/mapStore';
|
||||||
|
import { useThemeStore } from '@common/store/themeStore';
|
||||||
import {
|
import {
|
||||||
BASE_STYLE,
|
BASE_STYLE,
|
||||||
LIGHT_STYLE,
|
LIGHT_STYLE,
|
||||||
@ -7,11 +8,12 @@ import {
|
|||||||
ENC_EMPTY_STYLE,
|
ENC_EMPTY_STYLE,
|
||||||
} from '@common/components/map/mapStyles';
|
} from '@common/components/map/mapStyles';
|
||||||
|
|
||||||
export function useBaseMapStyle(lightMode = false): StyleSpecification {
|
export function useBaseMapStyle(): StyleSpecification {
|
||||||
|
const theme = useThemeStore((s) => s.theme);
|
||||||
const mapToggles = useMapStore((s) => s.mapToggles);
|
const mapToggles = useMapStore((s) => s.mapToggles);
|
||||||
|
|
||||||
if (mapToggles.s57) return ENC_EMPTY_STYLE;
|
if (mapToggles.s57) return ENC_EMPTY_STYLE;
|
||||||
if (mapToggles.threeD) return SATELLITE_3D_STYLE;
|
if (mapToggles.threeD) return SATELLITE_3D_STYLE;
|
||||||
if (lightMode) return LIGHT_STYLE;
|
if (theme === 'light') return LIGHT_STYLE;
|
||||||
return BASE_STYLE;
|
return BASE_STYLE;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -131,7 +131,7 @@ export function IncidentsView() {
|
|||||||
const [baselineLoaded, setBaselineLoaded] = useState(() => getCachedBaseline() !== null && getCachedZones() !== null)
|
const [baselineLoaded, setBaselineLoaded] = useState(() => getCachedBaseline() !== null && getCachedZones() !== null)
|
||||||
|
|
||||||
// Map style & toggles
|
// Map style & toggles
|
||||||
const currentMapStyle = useBaseMapStyle(true)
|
const currentMapStyle = useBaseMapStyle()
|
||||||
const mapToggles = useMapStore((s) => s.mapToggles)
|
const mapToggles = useMapStore((s) => s.mapToggles)
|
||||||
|
|
||||||
// Measure tool
|
// Measure tool
|
||||||
|
|||||||
@ -1240,7 +1240,6 @@ export function OilSpillView() {
|
|||||||
sensitiveResourceGeojson={
|
sensitiveResourceGeojson={
|
||||||
displayControls.showSensitiveResources ? sensitiveResourceGeojson : null
|
displayControls.showSensitiveResources ? sensitiveResourceGeojson : null
|
||||||
}
|
}
|
||||||
lightMode
|
|
||||||
centerPoints={centerPoints.filter((p) =>
|
centerPoints={centerPoints.filter((p) =>
|
||||||
visibleModels.has((p.model || 'OpenDrift') as PredictionModel),
|
visibleModels.has((p.model || 'OpenDrift') as PredictionModel),
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -59,7 +59,6 @@ const MapSlot = ({ label, step, mapData, captured, onCapture, onReset }: MapSlot
|
|||||||
simulationStartTime={mapData.simulationStartTime || undefined}
|
simulationStartTime={mapData.simulationStartTime || undefined}
|
||||||
mapCaptureRef={captureRef}
|
mapCaptureRef={captureRef}
|
||||||
showOverlays={false}
|
showOverlays={false}
|
||||||
lightMode
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{captured && (
|
{captured && (
|
||||||
|
|||||||
@ -2,27 +2,10 @@ import { useState, useEffect } from 'react';
|
|||||||
import { Map, useControl } from '@vis.gl/react-maplibre';
|
import { Map, useControl } from '@vis.gl/react-maplibre';
|
||||||
import { MapboxOverlay } from '@deck.gl/mapbox';
|
import { MapboxOverlay } from '@deck.gl/mapbox';
|
||||||
import { ScatterplotLayer } from '@deck.gl/layers';
|
import { ScatterplotLayer } from '@deck.gl/layers';
|
||||||
import type { StyleSpecification } from 'maplibre-gl';
|
|
||||||
import 'maplibre-gl/dist/maplibre-gl.css';
|
import 'maplibre-gl/dist/maplibre-gl.css';
|
||||||
import type { ScatDetail } from './scatTypes';
|
import type { ScatDetail } from './scatTypes';
|
||||||
import { hexToRgba } from '@common/components/map/mapUtils';
|
import { hexToRgba } from '@common/components/map/mapUtils';
|
||||||
|
import { useBaseMapStyle } from '@common/hooks/useBaseMapStyle';
|
||||||
// ── 베이스맵 스타일 ──────────────────────────────────────
|
|
||||||
const BASE_STYLE: StyleSpecification = {
|
|
||||||
version: 8,
|
|
||||||
sources: {
|
|
||||||
'carto-dark': {
|
|
||||||
type: 'raster',
|
|
||||||
tiles: [
|
|
||||||
'https://a.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}@2x.png',
|
|
||||||
'https://b.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}@2x.png',
|
|
||||||
'https://c.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}@2x.png',
|
|
||||||
],
|
|
||||||
tileSize: 256,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
layers: [{ id: 'carto-dark-layer', type: 'raster', source: 'carto-dark' }],
|
|
||||||
};
|
|
||||||
|
|
||||||
// ── DeckGLOverlay ──────────────────────────────────────
|
// ── DeckGLOverlay ──────────────────────────────────────
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
@ -94,12 +77,14 @@ function PopupMap({
|
|||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const currentMapStyle = useBaseMapStyle();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative w-full h-full">
|
<div className="relative w-full h-full">
|
||||||
<Map
|
<Map
|
||||||
key={`${lat}-${lng}`}
|
key={`${lat}-${lng}`}
|
||||||
initialViewState={{ longitude: lng, latitude: lat, zoom: 15 }}
|
initialViewState={{ longitude: lng, latitude: lat, zoom: 15 }}
|
||||||
mapStyle={BASE_STYLE}
|
mapStyle={currentMapStyle}
|
||||||
style={{ width: '100%', height: '100%' }}
|
style={{ width: '100%', height: '100%' }}
|
||||||
attributionControl={false}
|
attributionControl={false}
|
||||||
onLoad={onMapLoad}
|
onLoad={onMapLoad}
|
||||||
|
|||||||
불러오는 중...
Reference in New Issue
Block a user