diff --git a/src/components/main/MainUtm.jsx b/src/components/main/MainUtm.jsx index 43cd08a..1062419 100644 --- a/src/components/main/MainUtm.jsx +++ b/src/components/main/MainUtm.jsx @@ -1,35 +1,135 @@ +import { useEffect, useRef } from "react"; +import { gsap } from "gsap"; +import { ScrollTrigger } from "gsap/ScrollTrigger"; + +gsap.registerPlugin(ScrollTrigger); + function MainUtm() { + const sectionRef = useRef(null); + const stickyRef = useRef(null); + const trackRef = useRef(null); + const line1Ref = useRef(null); + const line2Ref = useRef(null); + const line3Ref = useRef(null); + const descRef = useRef(null); + const panelRef = useRef(null); + const frameRef = useRef(null); + const card1Ref = useRef(null); + const card2Ref = useRef(null); + const card3Ref = useRef(null); + const glowRef = useRef(null); + + useEffect(() => { + const ctx = gsap.context(() => { + gsap.set([line1Ref.current, line2Ref.current, line3Ref.current], { yPercent: 0 }); + gsap.set(line2Ref.current, { opacity: 0.18 }); + gsap.set(line3Ref.current, { opacity: 0.12 }); + gsap.set(descRef.current, { opacity: 0.35, y: 20 }); + gsap.set(panelRef.current, { scale: 0.92, y: 40, rotateX: 8 }); + gsap.set(card1Ref.current, { x: 40, y: 0, rotate: -6 }); + gsap.set(card2Ref.current, { x: 0, y: 0, rotate: 0 }); + gsap.set(card3Ref.current, { x: -40, y: 0, rotate: 6 }); + gsap.set(glowRef.current, { scale: 0.8, opacity: 0.3 }); + + const tl = gsap.timeline({ + scrollTrigger: { + trigger: sectionRef.current, + start: "top top", + end: "+=2200", + scrub: 1.1, + pin: stickyRef.current, + anticipatePin: 1, + }, + }); + + tl.to(line1Ref.current, { yPercent: -110, opacity: 0.08, ease: "none" }, 0) + .to(line2Ref.current, { yPercent: -102, opacity: 1, ease: "none" }, 0) + .to(descRef.current, { opacity: 0.7, y: 0, ease: "none" }, 0.08) + .to(panelRef.current, { scale: 1, y: 0, rotateX: 0, ease: "none" }, 0.02) + .to(card1Ref.current, { x: 0, y: -18, rotate: 0, ease: "none" }, 0.06) + .to(card2Ref.current, { y: -8, ease: "none" }, 0.08) + .to(card3Ref.current, { x: 0, y: 16, rotate: 0, ease: "none" }, 0.1) + .to(glowRef.current, { scale: 1.2, opacity: 0.55, ease: "none" }, 0.08) + + .to(line2Ref.current, { yPercent: -210, opacity: 0.08, ease: "none" }, 0.42) + .to(line3Ref.current, { yPercent: -196, opacity: 1, ease: "none" }, 0.42) + .to(descRef.current, { opacity: 1, ease: "none" }, 0.48) + .to(panelRef.current, { y: -12, scale: 1.03, ease: "none" }, 0.46) + .to(card1Ref.current, { x: -26, y: -28, scale: 0.96, opacity: 0.7, ease: "none" }, 0.46) + .to(card2Ref.current, { y: -18, scale: 1.04, ease: "none" }, 0.48) + .to(card3Ref.current, { x: 26, y: 24, scale: 0.96, opacity: 0.7, ease: "none" }, 0.46) + .to(glowRef.current, { scale: 1.45, opacity: 0.72, ease: "none" }, 0.48) + + .to(trackRef.current, { yPercent: -8, ease: "none" }, 0.68) + .to(panelRef.current, { scale: 1.08, y: -26, ease: "none" }, 0.68) + .to(descRef.current, { y: -8, ease: "none" }, 0.68); + }, sectionRef); + + return () => ctx.revert(); + }, []); + return ( -
-
-
-

UTM SYSTEM

-

드론 교통을 안전하게 관리하는 통합 관제 시스템

-
+
+
+
+
+

UTM SYSTEM

-
-
- 01 -

비행 요청

-

운영자는 비행 계획을 등록합니다

-
+
+

+ Monitor + the airspace +

-
- 02 -

자동 승인

-

공역과 규제 기준을 기반으로 승인됩니다

-
+

+ Approve + every mission +

+ +

+ Control + in real time +

+
-
- 03 -

경로 관리

-

비행 경로를 실시간으로 추적합니다

+

+ 실시간 모니터링, 자동 비행 승인, 운항 시뮬레이션과 영상 연계를 하나의 경험으로 구성한 통합 UTM 플랫폼 +

-
- 04 -

실시간 관제

-

이상 상황을 즉시 감지하고 대응합니다

+
+
+ +
+
+
+ Live Operations + + + System Active + +
+ +
+ +
+ Monitoring +

실시간 비행 상황 및 공역 상태 가시화

+
+ +
+ Approval +

비행 가능 여부 검토와 자동 승인 프로세스

+
+ +
+ Simulation +

운항 전 시뮬레이션과 상황 대응 연계

+
+ +
+
+
diff --git a/src/css/common.css b/src/css/common.css index b3b6336..d96f1ed 100644 --- a/src/css/common.css +++ b/src/css/common.css @@ -133,4 +133,91 @@ body{overflow-x:hidden;} .main-scroll-indicator{bottom:58px;} .main-scroll-line{height:22px;} .main-scroll-text{font-size:10px;letter-spacing:.22em;} +} + +.main-utm-section{position:relative;height:320vh;background:linear-gradient(180deg,#f6f8fc 0%,#eef3fb 100%);} + +.main-utm-sticky{position:sticky;top:0;height:100vh;overflow:hidden;} + +.main-utm-inner{display:grid;grid-template-columns:minmax(0,1.02fr) minmax(0,.98fr);align-items:center;gap:40px;max-width:1440px;height:100%;margin:0 auto;padding:0 40px;} + +.main-utm-copy{position:relative;z-index:2;} + +.main-utm-kicker{margin:0 0 28px;font-size:13px;line-height:1;font-weight:800;letter-spacing:.22em;color:#3A4081;} + +.main-utm-title-track{position:relative;height:260px;overflow:hidden;} + +.main-utm-line{display:block;margin:0;font-size:clamp(52px,7vw,104px);line-height:.96;font-weight:800;letter-spacing:-.06em;transform-origin:left center;will-change:transform,opacity;} + +.main-utm-line+.main-utm-line{margin-top:34px;} + +.main-utm-strong{color:#111827;} + +.main-utm-muted{color:#c3cad8;} + +.main-utm-desc{max-width:620px;margin:34px 0 0;font-size:18px;line-height:1.8;font-weight:500;color:#5b6474;word-break:keep-all;} + +.main-utm-showcase{position:relative;height:100%;display:flex;align-items:center;justify-content:center;} + +.main-utm-glow{position:absolute;top:50%;left:50%;width:760px;height:760px;border-radius:50%;background:radial-gradient(circle,rgba(58,64,129,.18) 0%,rgba(58,64,129,.08) 34%,rgba(58,64,129,0) 72%);transform:translate(-50%,-50%);filter:blur(18px);pointer-events:none;} + +.main-utm-panel-frame{position:relative;width:min(100%,640px);aspect-ratio:1/1.05;perspective:1200px;} + +.main-utm-panel{position:relative;width:100%;height:100%;border:1px solid rgba(255,255,255,.42);border-radius:34px;background:linear-gradient(180deg,rgba(12,18,33,.94) 0%,rgba(17,27,52,.98) 100%);box-shadow:0 40px 120px rgba(14,22,44,.28);overflow:hidden;transform-style:preserve-3d;} + +.main-utm-panel::before{content:"";position:absolute;inset:0;background:linear-gradient(135deg,rgba(255,255,255,.12) 0%,rgba(255,255,255,0) 38%);pointer-events:none;} + +.main-utm-panel-top{position:absolute;top:24px;left:24px;right:24px;display:flex;align-items:center;justify-content:space-between;z-index:3;} + +.main-utm-chip{display:inline-flex;align-items:center;height:38px;padding:0 14px;border:1px solid rgba(255,255,255,.14);border-radius:999px;background:rgba(255,255,255,.08);font-size:13px;font-weight:700;color:#f8fafc;} + +.main-utm-status{display:inline-flex;align-items:center;gap:8px;font-size:13px;font-weight:700;color:#d9e1f1;} + +.main-utm-status i{display:block;width:8px;height:8px;border-radius:50%;background:#4ade80;box-shadow:0 0 0 8px rgba(74,222,128,.12);} + +.main-utm-radar{position:absolute;inset:50% auto auto 50%;width:72%;aspect-ratio:1/1;border-radius:50%;transform:translate(-50%,-44%);background:radial-gradient(circle,rgba(58,64,129,.24) 0%,rgba(58,64,129,.12) 26%,rgba(58,64,129,.04) 46%,rgba(58,64,129,0) 66%);} + +.main-utm-radar::before{content:"";position:absolute;inset:10%;border:1px solid rgba(255,255,255,.12);border-radius:50%;} + +.main-utm-radar::after{content:"";position:absolute;inset:24%;border:1px solid rgba(255,255,255,.1);border-radius:50%;} + +.main-utm-grid-lines{position:absolute;inset:0;background-image:linear-gradient(rgba(255,255,255,.05) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,.05) 1px,transparent 1px);background-size:56px 56px;mask-image:linear-gradient(180deg,rgba(0,0,0,.12) 0%,rgba(0,0,0,.82) 36%,rgba(0,0,0,.82) 100%);pointer-events:none;} + +.main-utm-floating-card{position:absolute;z-index:3;width:220px;padding:20px 20px 18px;border:1px solid rgba(255,255,255,.12);border-radius:22px;background:linear-gradient(180deg,rgba(255,255,255,.14) 0%,rgba(255,255,255,.08) 100%);backdrop-filter:blur(16px);box-shadow:0 24px 48px rgba(0,0,0,.2);} + +.main-utm-floating-card strong{display:block;margin:0 0 8px;font-size:22px;line-height:1.1;font-weight:800;color:#fff;letter-spacing:-.03em;} + +.main-utm-floating-card p{margin:0;font-size:14px;line-height:1.6;font-weight:500;color:rgba(255,255,255,.72);word-break:keep-all;} + +.card-a{top:112px;right:-16px;} + +.card-b{left:42px;bottom:110px;width:250px;} + +.card-c{right:26px;bottom:38px;} + +@media (max-width:1100px){ +.main-utm-section{height:280vh;} +.main-utm-inner{grid-template-columns:1fr;gap:30px;padding:100px 24px 40px;} +.main-utm-copy{align-self:end;} +.main-utm-title-track{height:210px;} +.main-utm-showcase{align-items:flex-start;} +.main-utm-panel-frame{width:min(100%,620px);} +} + +@media (max-width:767px){ +.main-utm-section{height:260vh;} +.main-utm-inner{padding:88px 20px 30px;} +.main-utm-title-track{height:168px;} +.main-utm-line{font-size:clamp(38px,12vw,64px);} +.main-utm-line+.main-utm-line{margin-top:22px;} +.main-utm-desc{margin-top:24px;font-size:16px;line-height:1.7;} +.main-utm-panel-frame{aspect-ratio:1/1.12;} +.main-utm-panel{border-radius:26px;} +.main-utm-panel-top{top:18px;left:18px;right:18px;flex-direction:column;align-items:flex-start;gap:10px;} +.main-utm-floating-card{width:180px;padding:16px;border-radius:18px;} +.main-utm-floating-card strong{font-size:18px;} +.main-utm-floating-card p{font-size:13px;line-height:1.5;} +.card-a{top:96px;right:6px;} +.card-b{left:12px;bottom:96px;width:200px;} +.card-c{right:12px;bottom:20px;} } \ No newline at end of file