- SensorChart: 히스토리 1H/2H/3H/6H, 기압 SLP 보정, 데이터 범위 확장(y축 시작) - SensorChart Tooltip: KST 시간 포맷, 위치 상단 고정, 스타일 통일 - 지진 포인트 클릭 → 지도 flyTo + SeismicMarker 진도별 펄스 원형 표시 - SatelliteMap flyTo 지원 추가 - OilFacilityLayer: planned ring SVG 내부로 이동 (아이콘 중심 정렬 수정) - 밝은 테마 text-shadow CSS 변수 분리 (dark/light) - deploy.yml: SSH SCP+실행 각 3회 재시도 (kex_exchange 거부 대응) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
83 lines
2.5 KiB
TypeScript
83 lines
2.5 KiB
TypeScript
import { Marker } from 'react-map-gl/maplibre';
|
|
import './SeismicMarker.css';
|
|
|
|
interface Props {
|
|
lat: number;
|
|
lng: number;
|
|
magnitude: number;
|
|
place: string;
|
|
}
|
|
|
|
/**
|
|
* 진도 기반 영향 반경 (km → px 근사, zoom 8 기준)
|
|
* M2: ~5km, M3: ~15km, M4: ~40km, M5: ~100km, M6: ~200km
|
|
* zoom 8에서 약 1km ≈ 0.6px
|
|
*/
|
|
function getRadiusPx(magnitude: number): number {
|
|
const radiusKm = Math.pow(10, 0.5 * magnitude - 0.5);
|
|
return Math.max(20, Math.min(radiusKm * 0.6, 200));
|
|
}
|
|
|
|
function getMagnitudeColor(magnitude: number): string {
|
|
if (magnitude < 3) return 'rgba(251, 191, 36, 0.4)'; // yellow
|
|
if (magnitude < 4) return 'rgba(249, 115, 22, 0.4)'; // orange
|
|
if (magnitude < 5) return 'rgba(239, 68, 68, 0.4)'; // red
|
|
if (magnitude < 6) return 'rgba(220, 38, 38, 0.5)'; // dark red
|
|
return 'rgba(153, 27, 27, 0.6)'; // maroon
|
|
}
|
|
|
|
function getStrokeColor(magnitude: number): string {
|
|
if (magnitude < 3) return '#fbbf24';
|
|
if (magnitude < 4) return '#f97316';
|
|
if (magnitude < 5) return '#ef4444';
|
|
if (magnitude < 6) return '#dc2626';
|
|
return '#991b1b';
|
|
}
|
|
|
|
export function SeismicMarker({ lat, lng, magnitude, place }: Props) {
|
|
const size = getRadiusPx(magnitude) * 2;
|
|
const color = getMagnitudeColor(magnitude);
|
|
const stroke = getStrokeColor(magnitude);
|
|
|
|
return (
|
|
<Marker longitude={lng} latitude={lat} anchor="center">
|
|
<div className="seismic-marker-container" style={{ width: size, height: size }}>
|
|
{/* Outer pulse ring */}
|
|
<div
|
|
className="seismic-pulse-ring"
|
|
style={{
|
|
width: size,
|
|
height: size,
|
|
borderColor: stroke,
|
|
}}
|
|
/>
|
|
{/* Inner pulse ring */}
|
|
<div
|
|
className="seismic-pulse-ring seismic-pulse-ring-inner"
|
|
style={{
|
|
width: size * 0.6,
|
|
height: size * 0.6,
|
|
borderColor: stroke,
|
|
}}
|
|
/>
|
|
{/* Fill circle */}
|
|
<div
|
|
className="seismic-fill"
|
|
style={{
|
|
width: size,
|
|
height: size,
|
|
background: `radial-gradient(circle, ${color} 0%, transparent 70%)`,
|
|
}}
|
|
/>
|
|
{/* Center dot */}
|
|
<div className="seismic-center-dot" style={{ background: stroke }} />
|
|
{/* Label */}
|
|
<div className="seismic-label" style={{ color: stroke }}>
|
|
<span className="seismic-magnitude">M{magnitude.toFixed(1)}</span>
|
|
<span className="seismic-place">{place}</span>
|
|
</div>
|
|
</div>
|
|
</Marker>
|
|
);
|
|
}
|