기존 GhiVideo 저장소 HEAD의 트래킹 소스 362개 파일을 복제. (node_modules·storage·빌드 산출물·대용량 미디어는 .gitignore 규칙대로 제외) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
4.4 KiB
4.4 KiB
지도 기반 나침반(OSM, 노스업) 추가 + 타입 전환
소요 시간: 약 30분 Context 사용량: input ~340k / output ~9k tokens
요구
우측 상단 나침반을 2종 중 선택. 새 '지도 기반 나침반' = 나침반 안에 지도 + 실시간 위치. 사용자 선택: OSM 온라인 타일 · 노스업(북쪽 고정) · 화면표시 옵션에 전환 버튼.
구현
클라이언트
- store/settingsStore.ts:
compassType: 'analog'|'map'+ setter (persist). - components/overlay/MapCompass.tsx (신규):
- OSM 타일을 Web Mercator 로 배치, 원형 클립. 노스업(지도 고정) + 현재위치 중심 점 + 진행방향 화살표(yaw 회전) + 상단 N.
poseRef(부모 RAF 갱신 {lat,lon,yaw}) 를 내부 RAF 로 읽어: 화살표 즉시 회전 + 지도 팬(transform) + 임계 이동 시 타일 재배치(setState).- 타일 URL = 서버 프록시
/api/tile/{z}/{x}/{y}.png(외부 직접 로드는 CSP/COEP 로 차단됨).
- components/overlay/StationOverlay.tsx:
mapPoseRef추가, RAF 나침반 블록에서 headingDeg 항상 계산해 기록(아날로그 회전은 렌더 중일 때만).- 렌더: compassType 에 따라
<MapCompass>/<Minimap>선택. - 화면표시 옵션 '표시 토글'에 나침반 [눈금|지도] 버튼 추가.
서버 (프록시 필수)
- CSP
img-src 'self'+ COEPrequire-corp라 외부 타일<img>직접 로드 불가(elevation.ts 와 동일 제약). - server/src/routes/tile.ts (신규):
GET /api/tile/:z/:x/:y→ OSM 타일 fetch(식별 User-Agent) 후 같은 출처로 중계.Cross-Origin-Resource-Policy: same-origin, 7일 캐시, 좌표 검증(범위 밖 400). - server/src/app.ts:
app.use('/api/tile', tileRouter).
배포
- server/client 빌드 + PM2 restart ghiVideo(서버 라우트 반영 필수) 완료.
- 검증:
/api/tile/16/x/y.png→ 200 image/png, CORP same-origin, 7일 캐시. 범위 밖 → 400. 클라index-BS7bYMJ3.js.
추가: 줌 + 호버 확대 + 휠 줌
- settingsStore
compassZoom(12~19, 기본16) + setter(persist). MapCompass 에서 project(z 동적) 사용. - 나침반 하단 −/z/+ 버튼(pointer-events auto). 줌 변경 시 현재위치 기준 타일 재배치.
- 마우스 오버 → 2배 확대(transform scale, 우상단 고정 origin, 140ms), 벗어나면 원복.
- 휠 줌: 컨테이너 native wheel 리스너(passive:false) → deltaY 로 compassZoom ±1(위=확대).
- 호버/휠 위해 컨테이너 pointer-events auto(해당 영역만 이벤트 캡처).
개선(사용자 피드백)
- 확대: CSS scale(흐릿) → 위젯 지름 자체 확대(BASE_D 150 → HOVER_D 300, 타일 재배치) → 더 넓은 영역을 선명하게. 마우스 오버 시 확대, 벗어나면 기본 크기+기본 줌(16) 복귀.
- 방향 표시: 빨간 화살표 → 반투명 역삼각형(▽) = 드론 시야(중심에서 촬영방향으로 벌어짐, yaw 회전).
- 줌 +/− 버튼·z값 표시 삭제. 줌은 휠만(오버 중), 벗어나면 기본값.
- 상단 N: SVG text 로(위젯 크기에 맞춰 스케일) 크게·붉은색·반투명.
- settingsStore 의 compassZoom 제거(줌은 MapCompass 로컬 상태로 이동, 세션 임시).
추가: 위성지도 옵션
- 타일 프록시를 소스별로 확장: server/routes/tile.ts
GET /api/tile/:source/:z/:x/:y- source=osm → OpenStreetMap 일반, source=sat → Esri World Imagery 위성(z/row/col 순서, jpeg).
- settingsStore
compassMapStyle: 'street'|'sat'(persist). MapCompass 타일 URL/api/tile/${src}/.... - 화면표시 옵션에 지도 [일반|위성] 토글(지도 타입일 때만 노출).
- server 재빌드 + PM2 restart. 검증: osm→200 png, sat→200 jpeg.
- 주의: Esri World Imagery 는 출처표기 필요(내부 도구, 저부하). 대량이면 라이선스 검토.
주의/추후
- OSM 타일 사용 정책: 저부하 유지(줌16 고정 + 클라 96px 이동 시에만 재배치 + 서버 7일 캐시). 대량이면 자체 타일/유료 서비스 검토.
- 인터넷 없으면 타일 미표시(테두리/점/화살표만). 오프라인 필요 시 '노선 개요도(데이터 기반)' 타입 추가 검토.