diff --git a/frontend/src/tabs/aerial/components/RealtimeDrone.tsx b/frontend/src/tabs/aerial/components/RealtimeDrone.tsx index 3c01228..308b0e2 100644 --- a/frontend/src/tabs/aerial/components/RealtimeDrone.tsx +++ b/frontend/src/tabs/aerial/components/RealtimeDrone.tsx @@ -7,11 +7,11 @@ import type { DroneStreamItem } from '../services/aerialApi' import { CCTVPlayer } from './CCTVPlayer' import type { CCTVPlayerHandle } from './CCTVPlayer' -/** 드론 위치 좌표 (함정 모항 기준) */ -const DRONE_COORDS: Record = { - 'busan-1501': { lat: 35.0796, lon: 129.0756 }, - 'incheon-3008': { lat: 37.4541, lon: 126.5986 }, - 'mokpo-3015': { lat: 34.7780, lon: 126.3780 }, +/** 함정 위치 + 드론 비행 위치 */ +const DRONE_POSITIONS: Record = { + 'busan-1501': { ship: { lat: 35.0796, lon: 129.0756 }, drone: { lat: 35.1100, lon: 129.1100 } }, + 'incheon-3008': { ship: { lat: 37.4541, lon: 126.5986 }, drone: { lat: 37.4800, lon: 126.5600 } }, + 'mokpo-3015': { ship: { lat: 34.7780, lon: 126.3780 }, drone: { lat: 34.8050, lon: 126.4100 } }, } const DRONE_MAP_STYLE: StyleSpecification = { @@ -266,55 +266,61 @@ export function RealtimeDrone() { attributionControl={false} > {streams.map(stream => { - const coord = DRONE_COORDS[stream.id] - if (!coord) return null - const si = statusInfo(stream.status) + const pos = DRONE_POSITIONS[stream.id] + if (!pos) return null + const statusColor = stream.status === 'streaming' ? '#22c55e' : stream.status === 'starting' ? '#06b6d4' : stream.status === 'error' ? '#ef4444' : '#94a3b8' return ( { e.originalEvent.stopPropagation(); setMapPopup(stream) }} > -
- {/* 드론 SVG 아이콘 */} - +
+ + {/* 연결선 (점선) */} + + + {/* 함정 삼각형 (좌하단) */} + + + {/* 함정명 */} + + {stream.shipName.replace(/서 /, ' ')} + + {/* 드론 원형 아이콘 (우상단) */} + + {/* 드론 내부 — 십자 프로펠러 */} + + + {/* 프로펠러 4개 */} + + + + {/* 본체 */} - - {/* 팔 4개 */} - - - - - {/* 프로펠러 */} - - - - - {/* 카메라 */} - - {/* 송출중 표시 */} + + + {/* 송출중 LED */} {stream.status === 'streaming' && ( - - + + )} + {/* 드론 이름 */} + + {stream.droneModel.split(' ').slice(-1)[0]} - {/* 라벨 */} -
- {stream.shipName} -
) })} {/* 드론 클릭 팝업 */} - {mapPopup && DRONE_COORDS[mapPopup.id] && ( + {mapPopup && DRONE_POSITIONS[mapPopup.id] && ( setMapPopup(null)} closeOnClick={false}