|
|
|
@ -3,7 +3,16 @@ import SubHero from "../../components/SubHero"; |
|
|
|
import useFadeIn from "../../hooks/useFadeIn"; |
|
|
|
import useFadeIn from "../../hooks/useFadeIn"; |
|
|
|
|
|
|
|
|
|
|
|
import { motion, useInView } from "framer-motion"; |
|
|
|
import { motion, useInView } from "framer-motion"; |
|
|
|
import { MapPin, ShieldAlert, Network, BadgeCheck } from "lucide-react"; |
|
|
|
import { |
|
|
|
|
|
|
|
MapPin, |
|
|
|
|
|
|
|
ShieldAlert, |
|
|
|
|
|
|
|
Network, |
|
|
|
|
|
|
|
BadgeCheck, |
|
|
|
|
|
|
|
Cloud, |
|
|
|
|
|
|
|
FileCheck, |
|
|
|
|
|
|
|
Database, |
|
|
|
|
|
|
|
Layers, |
|
|
|
|
|
|
|
} from "lucide-react"; |
|
|
|
|
|
|
|
|
|
|
|
const ease = [0.22, 1, 0.36, 1]; |
|
|
|
const ease = [0.22, 1, 0.36, 1]; |
|
|
|
const basePath = import.meta.env.BASE_URL; |
|
|
|
const basePath = import.meta.env.BASE_URL; |
|
|
|
@ -21,6 +30,20 @@ const UTM_WHAT_LIST = [ |
|
|
|
"기상청 연계 기상 정보 자동 반영", |
|
|
|
"기상청 연계 기상 정보 자동 반영", |
|
|
|
"동적 공역 설정 및 지오펜싱 관리", |
|
|
|
"동적 공역 설정 및 지오펜싱 관리", |
|
|
|
]; |
|
|
|
]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const UTM_WHAT_LEFT = [ |
|
|
|
|
|
|
|
{ icon: MapPin, label: "실시간 위치 감시" }, |
|
|
|
|
|
|
|
{ icon: ShieldAlert, label: "충돌 위험 사전 분석" }, |
|
|
|
|
|
|
|
{ icon: Cloud, label: "기상 정보 자동 연계" }, |
|
|
|
|
|
|
|
{ icon: Network, label: "공역 설정·지오펜싱" }, |
|
|
|
|
|
|
|
]; |
|
|
|
|
|
|
|
const UTM_WHAT_RIGHT = [ |
|
|
|
|
|
|
|
{ icon: FileCheck, label: "비행 계획 및 경로 승인" }, |
|
|
|
|
|
|
|
{ icon: BadgeCheck, label: "불법 기체 실시간 감지" }, |
|
|
|
|
|
|
|
{ icon: Database, label: "비행 데이터 통합 관리" }, |
|
|
|
|
|
|
|
{ icon: Layers, label: "UAM·드론 시스템 연동" }, |
|
|
|
|
|
|
|
]; |
|
|
|
|
|
|
|
|
|
|
|
function IntroPage() { |
|
|
|
function IntroPage() { |
|
|
|
const ref = useFadeIn(); |
|
|
|
const ref = useFadeIn(); |
|
|
|
const UTM_NAV = [ |
|
|
|
const UTM_NAV = [ |
|
|
|
@ -91,9 +114,9 @@ function IntroPage() { |
|
|
|
<motion.li |
|
|
|
<motion.li |
|
|
|
key={card.label} |
|
|
|
key={card.label} |
|
|
|
className="utm-intro__card" |
|
|
|
className="utm-intro__card" |
|
|
|
initial={{ opacity: 0, y: 24 }} |
|
|
|
initial={{ opacity: 0, y: 60 }} |
|
|
|
animate={introInView ? { opacity: 1, y: 0 } : {}} |
|
|
|
animate={introInView ? { opacity: 1, y: 0 } : {}} |
|
|
|
transition={{ duration: 0.6, delay: 0.15 + i * 0.08, ease }} |
|
|
|
transition={{ duration: 0.8, delay: 0.2 + i * 0.12, ease }} |
|
|
|
> |
|
|
|
> |
|
|
|
<span className="utm-intro__card-num"> |
|
|
|
<span className="utm-intro__card-num"> |
|
|
|
{String(i + 1).padStart(2, "0")} |
|
|
|
{String(i + 1).padStart(2, "0")} |
|
|
|
@ -113,58 +136,63 @@ function IntroPage() { |
|
|
|
{/* ── UTM 소개 섹션 ── */} |
|
|
|
{/* ── UTM 소개 섹션 ── */} |
|
|
|
<section className="utm-what" ref={whatRef}> |
|
|
|
<section className="utm-what" ref={whatRef}> |
|
|
|
<div className="inner-wrap"> |
|
|
|
<div className="inner-wrap"> |
|
|
|
<div className="utm-what__inner"> |
|
|
|
{/* 상단 텍스트 */} |
|
|
|
<div className="utm-what__left"> |
|
|
|
<div className="utm-what__top"> |
|
|
|
<motion.span |
|
|
|
<motion.span |
|
|
|
className="utm-what__eyebrow" |
|
|
|
className="utm-what__eyebrow" |
|
|
|
initial={{ opacity: 0, y: 16 }} |
|
|
|
initial={{ opacity: 0, y: 16 }} |
|
|
|
animate={whatInView ? { opacity: 1, y: 0 } : {}} |
|
|
|
animate={whatInView ? { opacity: 1, y: 0 } : {}} |
|
|
|
transition={{ duration: 0.6, ease }} |
|
|
|
transition={{ duration: 0.6, ease }} |
|
|
|
> |
|
|
|
> |
|
|
|
What is UTM |
|
|
|
What is UTM |
|
|
|
</motion.span> |
|
|
|
</motion.span> |
|
|
|
|
|
|
|
|
|
|
|
<motion.h2 |
|
|
|
<motion.h2 |
|
|
|
className="utm-what__title" |
|
|
|
className="utm-what__title" |
|
|
|
initial={{ opacity: 0, y: 20 }} |
|
|
|
initial={{ opacity: 0, y: 20 }} |
|
|
|
animate={whatInView ? { opacity: 1, y: 0 } : {}} |
|
|
|
animate={whatInView ? { opacity: 1, y: 0 } : {}} |
|
|
|
transition={{ duration: 0.7, delay: 0.1, ease }} |
|
|
|
transition={{ duration: 0.7, delay: 0.1, ease }} |
|
|
|
> |
|
|
|
> |
|
|
|
UTM, |
|
|
|
UTM, <em>무엇을 할 수 있나요?</em> |
|
|
|
<br /> |
|
|
|
</motion.h2> |
|
|
|
무엇을 할 수 있나요? |
|
|
|
|
|
|
|
</motion.h2> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<motion.p |
|
|
|
<motion.p |
|
|
|
className="utm-what__desc" |
|
|
|
className="utm-what__desc" |
|
|
|
initial={{ opacity: 0, y: 16 }} |
|
|
|
initial={{ opacity: 0, y: 16 }} |
|
|
|
animate={whatInView ? { opacity: 1, y: 0 } : {}} |
|
|
|
animate={whatInView ? { opacity: 1, y: 0 } : {}} |
|
|
|
transition={{ duration: 0.6, delay: 0.2, ease }} |
|
|
|
transition={{ duration: 0.6, delay: 0.2, ease }} |
|
|
|
> |
|
|
|
> |
|
|
|
UTM은 단순한 관제 시스템을 넘어, 도심 저고도 공역 전체를 |
|
|
|
UTM은 단순한 관제 시스템을 넘어, 도심 저고도 공역 전체를 |
|
|
|
디지털로 운영하는 통합 플랫폼입니다. 실시간 감시부터 충돌 위험 |
|
|
|
디지털로 운영하는 통합 플랫폼입니다. 실시간 감시부터 충돌 위험 |
|
|
|
분석, 기상 연계, 공역 관리까지 — 비행의 모든 순간을 안전하게 |
|
|
|
분석, 기상 연계, 공역 관리까지 — 비행의 모든 순간을 안전하게 |
|
|
|
연결합니다. |
|
|
|
연결합니다. |
|
|
|
</motion.p> |
|
|
|
</motion.p> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<motion.ul |
|
|
|
{/* 3열 바디 */} |
|
|
|
className="utm-what__list" |
|
|
|
<div className="utm-what__body"> |
|
|
|
initial={{ opacity: 0, y: 16 }} |
|
|
|
{/* 왼쪽 카드 */} |
|
|
|
animate={whatInView ? { opacity: 1, y: 0 } : {}} |
|
|
|
<motion.ul |
|
|
|
transition={{ duration: 0.6, delay: 0.3, ease }} |
|
|
|
className="utm-what__cards" |
|
|
|
> |
|
|
|
initial={{ opacity: 0, x: -24 }} |
|
|
|
{UTM_WHAT_LIST.map((item) => ( |
|
|
|
|
|
|
|
<li key={item}> |
|
|
|
|
|
|
|
<span className="utm-what__list-dot" /> |
|
|
|
|
|
|
|
{item} |
|
|
|
|
|
|
|
</li> |
|
|
|
|
|
|
|
))} |
|
|
|
|
|
|
|
</motion.ul> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
<motion.div |
|
|
|
|
|
|
|
className="utm-what__right" |
|
|
|
|
|
|
|
initial={{ opacity: 0, x: 32 }} |
|
|
|
|
|
|
|
animate={whatInView ? { opacity: 1, x: 0 } : {}} |
|
|
|
animate={whatInView ? { opacity: 1, x: 0 } : {}} |
|
|
|
|
|
|
|
transition={{ duration: 0.7, delay: 0.3, ease }} |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
{UTM_WHAT_LEFT.map(({ icon: Icon, label }) => ( |
|
|
|
|
|
|
|
<li key={label} className="utm-what__card"> |
|
|
|
|
|
|
|
<span className="utm-what__card-icon"> |
|
|
|
|
|
|
|
<Icon size={16} /> |
|
|
|
|
|
|
|
</span> |
|
|
|
|
|
|
|
<span className="utm-what__card-label">{label}</span> |
|
|
|
|
|
|
|
</li> |
|
|
|
|
|
|
|
))} |
|
|
|
|
|
|
|
</motion.ul> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{/* 가운데 목업 (기존 코드 유지) */} |
|
|
|
|
|
|
|
<motion.div |
|
|
|
|
|
|
|
className="utm-what__mockup" |
|
|
|
|
|
|
|
initial={{ opacity: 0, y: 24 }} |
|
|
|
|
|
|
|
animate={whatInView ? { opacity: 1, y: 0 } : {}} |
|
|
|
transition={{ duration: 0.8, delay: 0.2, ease }} |
|
|
|
transition={{ duration: 0.8, delay: 0.2, ease }} |
|
|
|
> |
|
|
|
> |
|
|
|
<div |
|
|
|
<div |
|
|
|
@ -173,108 +201,104 @@ function IntroPage() { |
|
|
|
backgroundImage: `url(${basePath}images/utm_what_img.png)`, |
|
|
|
backgroundImage: `url(${basePath}images/utm_what_img.png)`, |
|
|
|
}} |
|
|
|
}} |
|
|
|
> |
|
|
|
> |
|
|
|
{/* 드론들 */} |
|
|
|
{/* 빨간 드론 - 공역 빨간 구역 (중앙) */} |
|
|
|
|
|
|
|
<div |
|
|
|
<div className="drone drone--1"> |
|
|
|
className="drone drone--1" |
|
|
|
<div className="drone__bg drone__bg--red"> |
|
|
|
style={{ top: "35%", left: "48%" }} |
|
|
|
<svg |
|
|
|
> |
|
|
|
width="20" |
|
|
|
<div className="drone__badge drone__badge--red"> |
|
|
|
height="20" |
|
|
|
<div className="drone__badge-top"> |
|
|
|
viewBox="0 0 24 24" |
|
|
|
<img |
|
|
|
fill="none" |
|
|
|
src={`${basePath}images/red_drone.png`} |
|
|
|
> |
|
|
|
alt="drone" |
|
|
|
<path |
|
|
|
width="16" |
|
|
|
d="M12 12m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" |
|
|
|
height="16" |
|
|
|
fill="#fff" |
|
|
|
|
|
|
|
/> |
|
|
|
/> |
|
|
|
<path |
|
|
|
<span className="drone__badge-conn">BLE</span> |
|
|
|
d="M4 4l4 4M20 4l-4 4M4 20l4-4M20 20l-4-4" |
|
|
|
</div> |
|
|
|
stroke="#fff" |
|
|
|
<span className="drone__badge-id">COLL-ACR-001</span> |
|
|
|
strokeWidth="2" |
|
|
|
<span className="drone__badge-status">13m/s / 100m</span> |
|
|
|
strokeLinecap="round" |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
<circle cx="4" cy="4" r="2" fill="#fff" /> |
|
|
|
|
|
|
|
<circle cx="20" cy="4" r="2" fill="#fff" /> |
|
|
|
|
|
|
|
<circle cx="4" cy="20" r="2" fill="#fff" /> |
|
|
|
|
|
|
|
<circle cx="20" cy="20" r="2" fill="#fff" /> |
|
|
|
|
|
|
|
</svg> |
|
|
|
|
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div className="drone__ping drone__ping--red" /> |
|
|
|
<div className="drone__ping drone__ping--red" /> |
|
|
|
<div className="drone__ping drone__ping--red drone__ping--delay" /> |
|
|
|
<div className="drone__ping drone__ping--red drone__ping--delay" /> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<div className="drone drone--2"> |
|
|
|
{/* 파란 드론 - 왼쪽 검은 구역 주위 */} |
|
|
|
<div className="drone__bg drone__bg--blue"> |
|
|
|
<div |
|
|
|
<svg |
|
|
|
className="drone drone--2" |
|
|
|
width="20" |
|
|
|
style={{ top: "25%", left: "22%" }} |
|
|
|
height="20" |
|
|
|
> |
|
|
|
viewBox="0 0 24 24" |
|
|
|
<div className="drone__badge drone__badge--blue"> |
|
|
|
fill="none" |
|
|
|
<div className="drone__badge-top"> |
|
|
|
> |
|
|
|
<img |
|
|
|
<path |
|
|
|
src={`${basePath}images/blue_drone.png`} |
|
|
|
d="M12 12m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" |
|
|
|
alt="drone" |
|
|
|
fill="#fff" |
|
|
|
width="16" |
|
|
|
/> |
|
|
|
height="16" |
|
|
|
<path |
|
|
|
|
|
|
|
d="M4 4l4 4M20 4l-4 4M4 20l4-4M20 20l-4-4" |
|
|
|
|
|
|
|
stroke="#fff" |
|
|
|
|
|
|
|
strokeWidth="2" |
|
|
|
|
|
|
|
strokeLinecap="round" |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
<circle cx="4" cy="4" r="2" fill="#fff" /> |
|
|
|
|
|
|
|
<circle cx="20" cy="4" r="2" fill="#fff" /> |
|
|
|
|
|
|
|
<circle cx="4" cy="20" r="2" fill="#fff" /> |
|
|
|
|
|
|
|
<circle cx="20" cy="20" r="2" fill="#fff" /> |
|
|
|
|
|
|
|
</svg> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
<div className="drone__ping drone__ping--blue" /> |
|
|
|
|
|
|
|
<div className="drone__ping drone__ping--blue drone__ping--delay" /> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div className="drone drone--3"> |
|
|
|
|
|
|
|
<div className="drone__bg drone__bg--blue"> |
|
|
|
|
|
|
|
<svg |
|
|
|
|
|
|
|
width="20" |
|
|
|
|
|
|
|
height="20" |
|
|
|
|
|
|
|
viewBox="0 0 24 24" |
|
|
|
|
|
|
|
fill="none" |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
<path |
|
|
|
|
|
|
|
d="M12 12m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" |
|
|
|
|
|
|
|
fill="#fff" |
|
|
|
|
|
|
|
/> |
|
|
|
/> |
|
|
|
<path |
|
|
|
<span className="drone__badge-conn">BLE</span> |
|
|
|
d="M4 4l4 4M20 4l-4 4M4 20l4-4M20 20l-4-4" |
|
|
|
</div> |
|
|
|
stroke="#fff" |
|
|
|
<span className="drone__badge-id">DJI-TEST-0005</span> |
|
|
|
strokeWidth="2" |
|
|
|
<span className="drone__badge-status"> |
|
|
|
strokeLinecap="round" |
|
|
|
LTE · 9m/s / 100m |
|
|
|
/> |
|
|
|
</span> |
|
|
|
<circle cx="4" cy="4" r="2" fill="#fff" /> |
|
|
|
|
|
|
|
<circle cx="20" cy="4" r="2" fill="#fff" /> |
|
|
|
|
|
|
|
<circle cx="4" cy="20" r="2" fill="#fff" /> |
|
|
|
|
|
|
|
<circle cx="20" cy="20" r="2" fill="#fff" /> |
|
|
|
|
|
|
|
</svg> |
|
|
|
|
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div className="drone__ping drone__ping--blue" /> |
|
|
|
<div className="drone__ping drone__ping--blue" /> |
|
|
|
<div className="drone__ping drone__ping--blue drone__ping--delay" /> |
|
|
|
<div className="drone__ping drone__ping--blue drone__ping--delay" /> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<div className="drone-alert"> |
|
|
|
{/* 주황 드론 - 오른쪽 분홍 구역 근처 */} |
|
|
|
<div className="drone-alert__dot" /> |
|
|
|
<div |
|
|
|
<div className="drone-alert__content"> |
|
|
|
className="drone drone--3" |
|
|
|
<p className="drone-alert__title">⚠ 불법 드론 감지</p> |
|
|
|
style={{ top: "58%", left: "72%" }} |
|
|
|
<p className="drone-alert__desc"> |
|
|
|
> |
|
|
|
식별 불가 기체 접근 중 <br /> GND-150m |
|
|
|
<div className="drone__badge drone__badge--orange"> |
|
|
|
</p> |
|
|
|
<div className="drone__badge-top"> |
|
|
|
<p className="drone-alert__pos">위치 37.5°N 126.9°E</p> |
|
|
|
<div className="drone__badge-top"> |
|
|
|
|
|
|
|
<img |
|
|
|
|
|
|
|
src={`${basePath}images/orange_drone.png`} |
|
|
|
|
|
|
|
alt="drone" |
|
|
|
|
|
|
|
width="16" |
|
|
|
|
|
|
|
height="16" |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
<span className="drone__badge-conn">LTE</span> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
<span className="drone__badge-id">FPA502</span> |
|
|
|
|
|
|
|
<span className="drone__badge-status"> |
|
|
|
|
|
|
|
338m / 172k/m / 81° |
|
|
|
|
|
|
|
<br /> |
|
|
|
|
|
|
|
126.745021/37.287339 |
|
|
|
|
|
|
|
</span> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div className="drone__ping drone__ping--orange" /> |
|
|
|
|
|
|
|
<div className="drone__ping drone__ping--orange drone__ping--delay" /> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</motion.div> |
|
|
|
</motion.div> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{/* 오른쪽 카드 */} |
|
|
|
|
|
|
|
<motion.ul |
|
|
|
|
|
|
|
className="utm-what__cards utm-what__cards--right" |
|
|
|
|
|
|
|
initial={{ opacity: 0, x: 24 }} |
|
|
|
|
|
|
|
animate={whatInView ? { opacity: 1, x: 0 } : {}} |
|
|
|
|
|
|
|
transition={{ duration: 0.7, delay: 0.3, ease }} |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
{UTM_WHAT_RIGHT.map(({ icon: Icon, label }) => ( |
|
|
|
|
|
|
|
<li |
|
|
|
|
|
|
|
key={label} |
|
|
|
|
|
|
|
className="utm-what__card utm-what__card--right" |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
<span className="utm-what__card-label">{label}</span> |
|
|
|
|
|
|
|
<span className="utm-what__card-icon"> |
|
|
|
|
|
|
|
<Icon size={16} /> |
|
|
|
|
|
|
|
</span> |
|
|
|
|
|
|
|
</li> |
|
|
|
|
|
|
|
))} |
|
|
|
|
|
|
|
</motion.ul> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</section> |
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
|
|
<div className="inner-wrap"> |
|
|
|
<div className="inner-wrap"> |
|
|
|
{/* ── DRONE → UATM 진화 섹션 ── */} |
|
|
|
{/* ── DRONE → UATM 진화 섹션 ── */} |
|
|
|
<section className="utm-evo"> |
|
|
|
<section className="utm-evo"> |
|
|
|
|