Browse Source

fix(home): 세계지도 실제 지형으로 교체 (Natural Earth 110m 육지)

- 손으로 찍은 저폴리 대륙(회색 얼룩) 제거 → world-atlas land-110m TopoJSON 을 등거리 투영(viewBox 1000×400, 위도 84~-60 크롭)으로 변환한 실제 육지 path(worldLandPath.ts, genmap 자동생성)
- 핀도 동일 투영으로 정확히 정렬. 남극 크롭으로 프레임 꽉 참
- world-map.scss: land polygon→path, non-scaling-stroke 해안선, 무대 비율 1000/400

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
KIM-JINO5 2 weeks ago
parent
commit
6e14beb670

+ 12 - 32
app/(main)/_components/WorldMarketMap.tsx

@@ -3,40 +3,22 @@
 import './world-map.scss';
 import { useMemo, useState } from 'react';
 import { EXCHANGE_GEO, moveDir, formatFlucRate, formatIndexClose, type WorldIndexRow } from '@/types/worldIndex';
+import { WORLD_LAND_PATH } from './worldLandPath';
 
-// 등거리(plate carrée) 투영 — viewBox 1000×500 (경도 -180~180, 위도 90~-90)
+// 등거리(plate carrée) 투영 — viewBox 1000×400, 경도 -180~180 → x, 위도 84~-60 → y (남극 크롭, 등scale).
+// WORLD_LAND_PATH(실제 Natural Earth 110m 육지) 도 동일 투영으로 생성되어 핀과 정확히 정렬된다.
 const VW = 1000;
-const VH = 500;
+const VH = 400;
+const LAT_MAX = 84;
+const LAT_SPAN = 144;
 const project = (lat: number, lng: number) => ({
 	x: ((lng + 180) / 360) * VW,
-	y: ((90 - lat) / 180) * VH
+	y: ((LAT_MAX - lat) / LAT_SPAN) * VH
 });
 
-// 스타일라이즈드(저폴리) 대륙 실루엣 — 지리적 근사(정밀 지도 아님). viewBox 좌표계 직접 좌표.
-const CONTINENTS: string[] = [
-	// 북미
-	'140,84 210,66 302,70 314,104 288,126 302,158 274,176 250,156 248,196 226,210 200,236 188,222 212,198 214,172 190,156 166,130 150,106',
-	// 그린란드
-	'330,54 366,48 380,74 352,92 332,76',
-	// 남미
-	'300,266 340,258 364,278 380,300 366,336 344,384 320,414 304,420 296,388 300,342 290,300 292,278',
-	// 유럽
-	'470,92 518,84 550,94 560,116 540,134 512,150 496,134 480,142 470,116',
-	// 아프리카
-	'486,176 548,166 588,188 596,236 570,300 542,358 520,350 508,298 500,244 488,206',
-	// 아시아(중동~러시아~중국~인도 벌지)
-	'560,92 634,68 714,70 792,82 858,98 900,120 872,140 852,150 872,178 830,198 800,178 810,214 776,234 748,208 720,180 700,206 686,182 656,168 628,146 600,150 580,128 566,110',
-	// 일본
-	'878,136 896,150 886,172 872,158',
-	// 인도네시아/동남아 도서
-	'756,234 806,230 830,248 800,264 760,258',
-	// 호주
-	'800,316 858,306 928,332 916,362 856,378 812,362 796,336'
-];
-
-// 위/경도 격자선
+// 위/경도 격자선 (크롭 위도 범위 내)
 const LNG_LINES = [-150, -120, -90, -60, -30, 0, 30, 60, 90, 120, 150];
-const LAT_LINES = [-60, -30, 0, 30, 60];
+const LAT_LINES = [-40, -20, 0, 20, 40, 60];
 
 type Props = {
 	rows: WorldIndexRow[];
@@ -125,16 +107,14 @@ export default function WorldMarketMap({ rows }: Props)
 								return <line key={`lng-${lng}`} x1={x} y1='0' x2={x} y2={VH} />;
 							})}
 							{LAT_LINES.map((lat) => {
-								const y = ((90 - lat) / 180) * VH;
+								const y = ((LAT_MAX - lat) / LAT_SPAN) * VH;
 								return <line key={`lat-${lat}`} x1='0' y1={y} x2={VW} y2={y} />;
 							})}
 						</g>
 
-						{/* 대륙 */}
+						{/* 대륙 (실제 Natural Earth 110m 육지) */}
 						<g className='world-map__land'>
-							{CONTINENTS.map((points, i) => (
-								<polygon key={i} points={points} />
-							))}
+							<path d={WORLD_LAND_PATH} />
 						</g>
 
 						{/* 핀 */}

+ 6 - 5
app/(main)/_components/world-map.scss

@@ -67,11 +67,11 @@
 		font-variant-numeric: tabular-nums;
 	}
 
-	// 무대 — 2:1 등거리 비율 고정, 툴팁 기준 컨테이너
+	// 무대 — 등거리 크롭 비율(1000×400) 고정, 툴팁 기준 컨테이너
 	&__stage {
 		position: relative;
 		width: 100%;
-		aspect-ratio: 1000 / 500;
+		aspect-ratio: 1000 / 400;
 	}
 
 	&__svg {
@@ -96,12 +96,13 @@
 		stroke-width: 1;
 	}
 
-	// 대륙
-	&__land polygon {
+	// 대륙 (실제 지형 path)
+	&__land path {
 		fill: var(--az-map-land);
 		stroke: var(--az-map-land-edge);
-		stroke-width: 1;
+		stroke-width: 0.6;
 		stroke-linejoin: round;
+		vector-effect: non-scaling-stroke;
 	}
 
 	// 핀 — 그룹 color 로 방향색을 상속, dot/pulse 는 currentColor

File diff suppressed because it is too large
+ 1 - 0
app/(main)/_components/worldLandPath.ts


Some files were not shown because too many files changed in this diff