diff --git a/public/images/fc_aircraft.png b/public/images/fc_aircraft.png new file mode 100644 index 0000000..4ccfc0d Binary files /dev/null and b/public/images/fc_aircraft.png differ diff --git a/public/images/fc_bottom_tab.png b/public/images/fc_bottom_tab.png new file mode 100644 index 0000000..cb39e93 Binary files /dev/null and b/public/images/fc_bottom_tab.png differ diff --git a/public/images/fc_car.png b/public/images/fc_car.png new file mode 100644 index 0000000..4d51ca5 Binary files /dev/null and b/public/images/fc_car.png differ diff --git a/public/images/fc_computer.png b/public/images/fc_computer.png new file mode 100644 index 0000000..0928395 Binary files /dev/null and b/public/images/fc_computer.png differ diff --git a/public/images/fc_drone.png b/public/images/fc_drone.png new file mode 100644 index 0000000..8545e56 Binary files /dev/null and b/public/images/fc_drone.png differ diff --git a/public/images/fc_left_tab.png b/public/images/fc_left_tab.png new file mode 100644 index 0000000..a00a8da Binary files /dev/null and b/public/images/fc_left_tab.png differ diff --git a/public/images/fc_right_tab.png b/public/images/fc_right_tab.png new file mode 100644 index 0000000..6c54cd7 Binary files /dev/null and b/public/images/fc_right_tab.png differ diff --git a/public/images/fc_tab_airplane.png b/public/images/fc_tab_airplane.png new file mode 100644 index 0000000..70aeedf Binary files /dev/null and b/public/images/fc_tab_airplane.png differ diff --git a/public/images/fc_tab_car.png b/public/images/fc_tab_car.png new file mode 100644 index 0000000..3c11e42 Binary files /dev/null and b/public/images/fc_tab_car.png differ diff --git a/public/images/fc_tab_drone.png b/public/images/fc_tab_drone.png new file mode 100644 index 0000000..04bc959 Binary files /dev/null and b/public/images/fc_tab_drone.png differ diff --git a/public/images/fc_tab_vessel.png b/public/images/fc_tab_vessel.png new file mode 100644 index 0000000..89d31af Binary files /dev/null and b/public/images/fc_tab_vessel.png differ diff --git a/public/images/fc_tablet.png b/public/images/fc_tablet.png new file mode 100644 index 0000000..dca1d99 Binary files /dev/null and b/public/images/fc_tablet.png differ diff --git a/public/images/fc_tablet2.png b/public/images/fc_tablet2.png new file mode 100644 index 0000000..5942916 Binary files /dev/null and b/public/images/fc_tablet2.png differ diff --git a/public/images/fc_vessel.png b/public/images/fc_vessel.png new file mode 100644 index 0000000..4888069 Binary files /dev/null and b/public/images/fc_vessel.png differ diff --git a/src/css/common.css b/src/css/common.css index 9b48073..82e026c 100644 --- a/src/css/common.css +++ b/src/css/common.css @@ -655,14 +655,17 @@ body{overflow-x:hidden;} FlightControlPage — common.css 추가분 ════════════════════════════════ */ -.fc-eyebrow {display:block;font-size:.72rem;font-weight:700;letter-spacing:.2em;text-transform:uppercase;color:var(--color-primary);margin-bottom:1.5rem;} -.fc-eyebrow--light {color:rgba(255,255,255,.45);} +.fc-eyebrow { display: flex; align-items: center; gap: 8px; font-size: 11px; font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase; color: #8895c0; margin-bottom: 1.5rem; } +.fc-eyebrow::before { content: ''; display: block; width: 20px; height: 2px; background: linear-gradient(90deg, #e91e8c, #6b21a8); } + +.fc-eyebrow--light { color: rgba(255,255,255,0.45); } +.fc-eyebrow--light::before { background: rgba(255,255,255,0.4); } .fc-section-title {display:block;font-size:1.5rem;font-weight:700;color:var(--color-primary);margin-bottom:2.5rem;letter-spacing:-.01em;} /* ════════════════ 1. 개요 ════════════════ */ -.fc-overview {position:relative;border-radius:1.25rem;overflow:hidden;margin:3rem 0 4rem;min-height:520px;display:flex;align-items:flex-end;} +.fc-overview { position: relative; border-radius: 1.25rem; overflow: hidden; margin: 3rem 0 6rem; min-height: 520px; display: flex; align-items: flex-end; } .fc-overview__bg {position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block;filter:brightness(.38) saturate(.6);} .fc-overview__overlay {position:absolute;inset:0;background:linear-gradient(170deg, rgba(26,31,94,.6) 0%, rgba(26,31,94,.92) 60%);pointer-events:none;} .fc-overview__content {position:relative;z-index:1;padding:3.5rem 3.5rem 4rem;width:100%;} @@ -678,9 +681,50 @@ body{overflow-x:hidden;} .fc-badge--light:hover {background:rgba(255,255,255,.18);border-color:rgba(255,255,255,.3);color:#fff;} /* ════════════════ - 2. 수치 지표 + 2. intro ════════════════ */ -.fc-stats {display:grid;grid-template-columns:repeat(4,1fr);gap:0;margin-bottom:6rem;border:1px solid var(--color-primary-soft-border);border-radius:1rem;overflow:hidden;} + +.fc-intro { display: flex; gap: 48px; align-items: center; margin: 0 0 8rem; } +.fc-intro__left { flex: 1; } +.fc-intro__title { font-size: 2rem; font-weight: 800; color: #1a1f3a; line-height: 1.35; letter-spacing: -0.02em; margin: 16px 0 28px; } +.fc-intro__desc { font-size: 0.9rem; color: #666; line-height: 1.9; margin-bottom: 48px; } +.fc-intro__icons { display: flex; gap: 32px; } +.fc-intro__icon-item { display: flex; flex-direction: column; align-items: center; gap: 10px; } +.fc-intro__icon-item img { width: 80px; height: 80px; object-fit: contain; } +.fc-intro__icon-item span { font-size: 0.75rem; font-weight: 600; color: #888; } +.fc-intro__right { flex: 0 0 52%; } +.fc-intro__monitor { width: 100%; object-fit: contain; display: block; } + +/* ════════════════ + 3. 기능 하이라이트 +════════════════ */ +.fc-highlight { display: grid; grid-template-columns: 1fr 1fr; gap: 48px; margin-bottom: 8rem; align-items: center; } +.fc-highlight__item { display: flex; gap: 24px; align-items: center; } +.fc-highlight__text { flex: 0 0 40%; } +.fc-highlight__title { font-size: 1.75rem; font-weight: 800; color: #1a1f3a; line-height: 1.35; letter-spacing: -0.02em; margin: 10px 0 16px; } +.fc-highlight__desc { font-size: 0.88rem; color: #666; line-height: 1.9; } +.fc-highlight__img-wrap { flex: 1; } +.fc-highlight__img-wrap img { width: 100%; object-fit: contain; display: block; } +.fc-highlight__img-scene { position: relative; width: 100%; } +.fc-highlight__tablet { width: 100%; object-fit: contain; display: block; } +.fc-highlight__float-icon { position: absolute; width: 72px; height: 72px; object-fit: contain; filter: drop-shadow(0 8px 16px rgba(0,0,0,0.15)); } +.fc-situation { position: relative; width: 100%; } +/* 메인 이미지 크기 */ +.fc-situation__main { width: 100%; object-fit: contain; display: block; } + +/* 왼쪽 탭 위치/크기 */ +.fc-situation__left { position: absolute; left: -25%; top: 10%; width: 70% !important; object-fit: contain; } + +/* 오른쪽 탭 위치/크기 */ +.fc-situation__right { position: absolute; right: -20%; top: 20%; width: 70% !important; object-fit: contain; } + +/* 아래 탭 위치/크기 */ +.fc-situation__bottom { position: absolute; bottom: -40%; left: -5%; width: 60%; object-fit: contain; } + +/* ════════════════ + 4. 수치 지표 +════════════════ */ +.fc-stats { display: grid; grid-template-columns: repeat(4,1fr); gap: 0; margin-bottom: 8rem; border: 1px solid var(--color-primary-soft-border); border-radius: 1rem; overflow: hidden; } .fc-stat-item {display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;padding:2.5rem 1.5rem;text-align:center;border-right:1px solid var(--color-primary-soft-border);transition:background .2s;} .fc-stat-item:last-child {border-right:none;} .fc-stat-item:hover {background:var(--color-primary-soft);} @@ -688,9 +732,9 @@ body{overflow-x:hidden;} .fc-stat-item__label {font-size:.8rem;font-weight:500;color:#888;line-height:1.4;} /* ════════════════ - 3. 적용 분야 + 5. 적용 분야 ════════════════ */ -.fc-domains {margin-bottom:6rem;} +.fc-domains { margin-bottom: 8rem; } .fc-domains__grid {display:grid;grid-template-columns:repeat(5,1fr);gap:1.25rem;} .fc-domain-card {display:flex;flex-direction:column;gap:.75rem;padding:1.75rem 1.5rem;border:1px solid var(--color-primary-soft-border);border-radius:1rem;background:#fff;transition:border-color .2s,box-shadow .2s;cursor:default;} .fc-domain-card:hover {border-color:var(--color-primary-border);box-shadow:0 8px 28px var(--color-primary-shadow);} @@ -700,9 +744,9 @@ body{overflow-x:hidden;} .fc-domain-card__desc {font-size:.78rem;line-height:1.65;color:#888;margin:0;} /* ════════════════ - 4. 주요기능 + 6. 주요기능 ════════════════ */ -.fc-functions {margin-bottom:6rem;} +.fc-functions { margin-bottom: 8rem; } .fc-functions__body {display:flex;gap:5rem;align-items:flex-start;} .fc-func-list {flex:1;list-style:none;margin:0;padding:0;} @@ -723,9 +767,9 @@ body{overflow-x:hidden;} .fc-func-display__label {font-size:.78rem;font-weight:600;color:#fff;} /* ════════════════ - 5. 시스템 구성 + 7. 시스템 구성 ════════════════ */ -.fc-flow {padding-bottom:8rem;} +.fc-flow { padding-bottom: 10rem; } .fc-flow__row {display:flex;align-items:flex-start;gap:0;} .fc-flow__item {position:relative;flex:1;display:flex;flex-direction:column;align-items:center;text-align:center;gap:.6rem;padding:2rem 1rem;} .fc-flow__step {font-size:.68rem;font-weight:800;letter-spacing:.12em;color:var(--color-primary-border-strong);} @@ -786,8 +830,14 @@ body{overflow-x:hidden;} .fc-flow__arrow { display: none; } + .fc-highlight { grid-template-columns: 1fr; gap: 48px; } + .fc-highlight__item { flex-direction: column; } + .fc-highlight__img-wrap { width: 100%; } + } + + @media (max-width: 640px) { .fc-overview { border-radius: .875rem; @@ -805,4 +855,15 @@ body{overflow-x:hidden;} .fc-func-item__label { font-size: .9rem; } + .fc-intro { flex-direction: column; } + .fc-intro__right { width: 100%; } + .fc-intro__title { font-size: 1.5rem; } + .fc-highlight { gap: 32px; margin-bottom: 5rem; } + .fc-highlight__item { gap: 16px; } + .fc-highlight__title { font-size: 1.3rem; } + .fc-highlight__desc { font-size: 0.82rem; } + .fc-highlight__float-icon { width: 48px; height: 48px; } + .fc-highlight__img-scene { transform: scale(0.75); transform-origin: top center; } + + } \ No newline at end of file diff --git a/src/pages/solution/FlightControlPage.jsx b/src/pages/solution/FlightControlPage.jsx index 3f8dee0..67b8012 100644 --- a/src/pages/solution/FlightControlPage.jsx +++ b/src/pages/solution/FlightControlPage.jsx @@ -1,12 +1,24 @@ import { useRef, useState } from "react"; import { motion, useInView, AnimatePresence } from "framer-motion"; -import { Radio, Puzzle, Network, Expand, Shield, ArrowUpRight, Package, Wind, AlertTriangle, Ship, Plane } from "lucide-react"; +import { + Radio, + Puzzle, + Network, + Expand, + Shield, + ArrowUpRight, + Package, + Wind, + AlertTriangle, + Ship, + Plane, +} from "lucide-react"; import SubHero from "../../components/SubHero"; import useFadeIn from "../../hooks/useFadeIn"; const SOLUTION_NAV = [ { label: "비행상황관리 시스템", to: "/solution/flight-control" }, - { label: "IBE", to: "/solution/ibe" }, + { label: "IBE (Internet Booking Engine)", to: "/solution/ibe" }, { label: "스마트 관광 예약 플랫폼", to: "/solution/smart-tour" }, { label: "KT G-cloud 인천총판", to: "/solution/kt-gcloud" }, ]; @@ -27,25 +39,57 @@ const STATS = [ ]; const DOMAINS = [ - { icon: Package, label: "드론 물류·배송 관제", desc: "도심 및 광역 드론 배송 경로 최적화 및 실시간 위치 관제" }, - { icon: Plane, label: "UAM 도심항공 모빌리티", desc: "미래형 도심 항공 교통 인프라 연계 관제 시스템" }, - { icon: Wind, label: "무인기 환경측정", desc: "대기질·기상 데이터 수집 드론 운용 및 모니터링" }, - { icon: AlertTriangle, label: "안티드론 보안관제", desc: "비인가 드론 탐지·추적 및 무력화 대응 지원" }, - { icon: Ship, label: "선박·항공기 통합관제", desc: "해상·공중 복합 식별정보 수집 및 통합 상황관리" }, + { + icon: Package, + label: "드론 물류·배송 관제", + desc: "도심 및 광역 드론 배송 경로 최적화 및 실시간 위치 관제", + }, + { + icon: Plane, + label: "UAM 도심항공 모빌리티", + desc: "미래형 도심 항공 교통 인프라 연계 관제 시스템", + }, + { + icon: Wind, + label: "무인기 환경측정", + desc: "대기질·기상 데이터 수집 드론 운용 및 모니터링", + }, + { + icon: AlertTriangle, + label: "안티드론 보안관제", + desc: "비인가 드론 탐지·추적 및 무력화 대응 지원", + }, + { + icon: Ship, + label: "선박·항공기 통합관제", + desc: "해상·공중 복합 식별정보 수집 및 통합 상황관리", + }, ]; const FUNCTIONS = [ { num: "01", img: "./images/s1-01.jpg", label: "비행가능 지역 및 공역표출" }, { num: "02", img: "./images/s1-02.jpg", label: "비행체 위치 표출" }, - { num: "03", img: "./images/s1-03.jpg", label: "항공기 비행경로 및 히스토리 표출" }, + { + num: "03", + img: "./images/s1-03.jpg", + label: "항공기 비행경로 및 히스토리 표출", + }, { num: "04", img: "./images/s1-04.jpg", label: "항공기 비행정보 표출" }, { num: "05", img: "./images/s1-05.jpg", label: "비행계획서 조회" }, { num: "06", img: "./images/s1-06.jpg", label: "비정상 상황의 경보 표출" }, ]; const FLOW = [ - { step: "01", label: "비행체 식별", desc: "항공기·드론·선박 실시간 신호 수집" }, - { step: "02", label: "데이터 수집", desc: "위치·속도·고도·식별코드 통합 처리" }, + { + step: "01", + label: "비행체 식별", + desc: "항공기·드론·선박 실시간 신호 수집", + }, + { + step: "02", + label: "데이터 수집", + desc: "위치·속도·고도·식별코드 통합 처리", + }, { step: "03", label: "관제 서버", desc: "통합 관제 서버 분석 및 상황 판단" }, { step: "04", label: "모니터링", desc: "관제사 화면 실시간 현황 표출" }, { step: "05", label: "경보·대응", desc: "이상 상황 감지 즉시 경보 및 대응" }, @@ -56,7 +100,12 @@ const ease = [0.22, 1, 0.36, 1]; function RevealText({ children, delay = 0, className }) { return (
- + {children}
@@ -66,10 +115,22 @@ function RevealText({ children, delay = 0, className }) { function StaggerWords({ text, delay = 0, className }) { const words = text.split(" "); return ( - + {words.map((word, i) => ( - + {word} @@ -79,6 +140,8 @@ function StaggerWords({ text, delay = 0, className }) { } function FlightControlPage() { + const basePath = import.meta.env.BASE_URL; + const ref = useFadeIn(); const [activeIdx, setActiveIdx] = useState(0); @@ -87,8 +150,17 @@ function FlightControlPage() { const domainsRef = useRef(null); const funcRef = useRef(null); const flowRef = useRef(null); - - const overviewInView = useInView(overviewRef, { once: true, margin: "-60px" }); + const introRef = useRef(null); + const introInView = useInView(introRef, { once: true, margin: "-60px" }); + const highlightRef = useRef(null); + const highlightInView = useInView(highlightRef, { + once: true, + margin: "-60px", + }); + const overviewInView = useInView(overviewRef, { + once: true, + margin: "-60px", + }); const statsInView = useInView(statsRef, { once: true, margin: "-60px" }); const domainsInView = useInView(domainsRef, { once: true, margin: "-60px" }); const funcInView = useInView(funcRef, { once: true, margin: "-80px" }); @@ -96,30 +168,71 @@ function FlightControlPage() { return (
- Flight Management} navItems={SOLUTION_NAV} /> + Flight Management} + navItems={SOLUTION_NAV} + />
{/* 1. 개요 */}
- +
{overviewInView && ( - + 비행상황 관리 시스템 )} {overviewInView && (
- +
)} - -

각종 드론 상황관제, 환경측정, 미래산업인 드론/PAV/UAM을 활용한 사업들을 지원하기 위한 환경/물류/안티 드론 등의 상황관제 시스템을 연구하고 솔루션을 제공합니다.

+ +

+ 각종 드론 상황관제, 환경측정, 미래산업인 드론/PAV/UAM을 활용한 + 사업들을 지원하기 위한 환경/물류/안티 드론 등의 상황관제 + 시스템을 연구하고 솔루션을 제공합니다. +

{FEATURES.map(({ icon: Icon, label }, i) => ( - + {label} @@ -129,10 +242,215 @@ function FlightControlPage() {
+ {/* 개요 인트로 */} +
+
+ + Overview + + + 모든 이동체 정보를 +
+ 하나의 플랫폼에서 +
+ + 항공기, 무인기, 선박, 지상 이동체의 실시간 정보를 통합 + 모니터링하고
+ 상황을 인식하여 신속하고 안전한 운영 의사결정을 지원합니다. +
+ + {[ + { img: "fc_aircraft.png", label: "항공기" }, + { img: "fc_drone.png", label: "무인기" }, + { img: "fc_vessel.png", label: "선박" }, + { img: "fc_car.png", label: "차량 등" }, + ].map((item, i) => ( +
+ {item.label} + {item.label} +
+ ))} +
+
+ + + 비행상황관리 시스템 + +
+ + {/* 기능 하이라이트 */} +
+ {[ + { + tag: "Real-Time Monitoring", + title: "실시간 이동체 정보 기반\n통합 모니터링", + desc: "전체에 분산된 이동체의 위치와 상태를 실시간으로 추적하여 안전하고 효율적인 운영을 지원합니다.", + img: "fc_tablet.png", + icons: [ + { + img: "fc_tab_airplane.png", + x: "0%", + y: "8%", + delay: 0, + move: { x: [-40, -120, 0], y: [0, 90, 0] }, // 왼쪽 아래 (배 방향) + }, + + { + img: "fc_tab_vessel.png", + x: "-30%", + y: "42%", + delay: 0, + move: { x: [0, 110, 0], y: [0, 60, 0] }, // 오른쪽 아래 (자동차 방향) + }, + + { + img: "fc_tab_car.png", + x: "0%", + y: "64%", + delay: 0, + move: { x: [0, 120, 0], y: [0, -65, 0] }, // 오른쪽 위 (드론 방향) + }, + { + img: "fc_tab_drone.png", + x: "30%", + y: "40%", + delay: 0, + move: { x: [0, -100, 0], y: [0, -50, 0] }, // 왼쪽 위 (비행기 방향) + }, + ], + }, + { + tag: "Situational Awareness", + title: "상황 인식 및\n의사결정 지원", + desc: "다양한 데이터와 고도화된 분석을 통해 상황을 예측하고 최적의 의사결정을 지원합니다.", + img: "fc_tablet2.png", + icons: null, + }, + ].map((item, i) => ( + +
+ {item.tag} +

+ {item.title.split("\n").map((line, j) => ( + + {line} +
+
+ ))} +

+

{item.desc}

+
+
+
+ {item.tag} + {item.icons && + item.icons.map((icon, j) => ( + + ))} + + {i === 1 && ( + <> + + + + + )} +
+
+
+ ))} +
{/* 2. 수치 지표 */}
{STATS.map(({ value, label }, i) => ( - + {value} {label} @@ -141,12 +459,24 @@ function FlightControlPage() { {/* 3. 적용 분야 */}
- + 적용 분야
{DOMAINS.map(({ icon: Icon, label, desc }, i) => ( - +
@@ -159,31 +489,79 @@ function FlightControlPage() { {/* 4. 주요기능 */}
- + 주요기능
    {FUNCTIONS.map(({ num, label }, i) => ( - setActiveIdx(i)} initial={{ opacity: 0, y: 16 }} animate={funcInView ? { opacity: 1, y: 0 } : {}} transition={{ duration: 0.5, ease, delay: 0.05 * i }}> + setActiveIdx(i)} + initial={{ opacity: 0, y: 16 }} + animate={funcInView ? { opacity: 1, y: 0 } : {}} + transition={{ duration: 0.5, ease, delay: 0.05 * i }} + > {num} {label} - + - + ))}
- - {FUNCTIONS[activeIdx].label} + + {FUNCTIONS[activeIdx].label}
- + {FUNCTIONS[activeIdx].num} - + {FUNCTIONS[activeIdx].label}
@@ -195,16 +573,38 @@ function FlightControlPage() { {/* 5. 시스템 구성 흐름 */}
- + 시스템 구성
{FLOW.map(({ step, label, desc }, i) => ( - + {step} {label}

{desc}

- {i < FLOW.length - 1 && } + {i < FLOW.length - 1 && ( + + )} ))}