3 changed files with 132 additions and 1 deletions
@ -0,0 +1,109 @@
|
||||
import { useEffect, useRef } from "react"; |
||||
import { gsap } from "gsap"; |
||||
import { ScrollTrigger } from "gsap/ScrollTrigger"; |
||||
|
||||
gsap.registerPlugin(ScrollTrigger); |
||||
|
||||
function MainNews() { |
||||
const sectionRef = useRef(null); |
||||
const headRef = useRef(null); |
||||
const itemsRef = useRef([]); |
||||
|
||||
const news = [ |
||||
{ |
||||
date: "2025.00.00", |
||||
title: "PAL Networks, 항공 IT 서비스 고도화 추진", |
||||
desc: "항공 운항 관리와 예약 플랫폼을 연결하는 통합 서비스 환경을 확대합니다.", |
||||
}, |
||||
{ |
||||
date: "2025.00.00", |
||||
title: "스마트 관광 예약 플랫폼 기능 확장", |
||||
desc: "관광 상품, 예약 데이터, 사용자 경험을 하나의 흐름으로 개선합니다.", |
||||
}, |
||||
{ |
||||
date: "2025.00.00", |
||||
title: "클라우드 기반 항공 서비스 운영 환경 구축", |
||||
desc: "안정적인 공공 클라우드 인프라를 기반으로 서비스 운영 효율을 높입니다.", |
||||
}, |
||||
]; |
||||
|
||||
useEffect(() => { |
||||
const ctx = gsap.context(() => { |
||||
gsap.set(headRef.current, { opacity: 0, y: 48 }); |
||||
gsap.set(itemsRef.current, { opacity: 0, y: 36 }); |
||||
|
||||
gsap |
||||
.timeline({ |
||||
scrollTrigger: { |
||||
trigger: sectionRef.current, |
||||
start: "top 70%", |
||||
end: "top 30%", |
||||
scrub: 1, |
||||
}, |
||||
}) |
||||
.to(headRef.current, { |
||||
opacity: 1, |
||||
y: 0, |
||||
duration: 0.8, |
||||
ease: "power2.out", |
||||
}) |
||||
.to( |
||||
itemsRef.current, |
||||
{ |
||||
opacity: 1, |
||||
y: 0, |
||||
stagger: 0.14, |
||||
duration: 0.75, |
||||
ease: "power2.out", |
||||
}, |
||||
"-=0.35", |
||||
); |
||||
}, sectionRef); |
||||
|
||||
return () => ctx.revert(); |
||||
}, []); |
||||
|
||||
return ( |
||||
<section className="main-news-section" ref={sectionRef}> |
||||
<div className="main-news-inner"> |
||||
<div className="main-news-head" ref={headRef}> |
||||
<p className="main-news-eyebrow">INSIDE PAL</p> |
||||
<h2 className="main-news-title"> |
||||
새로운 항공 서비스와 |
||||
<br /> |
||||
기술 소식 |
||||
</h2> |
||||
<p className="main-news-desc"> |
||||
항공 IT 플랫폼 구축, 서비스 운영, 기술 개발 관련 소식을 전합니다. |
||||
</p> |
||||
</div> |
||||
|
||||
<div className="main-news-list"> |
||||
{news.map((item, index) => ( |
||||
<article |
||||
className="main-news-item" |
||||
key={index} |
||||
ref={(el) => { |
||||
itemsRef.current[index] = el; |
||||
}} |
||||
> |
||||
<div className="main-news-meta"> |
||||
<span>NEWS</span> |
||||
<em>{item.date}</em> |
||||
</div> |
||||
|
||||
<div className="main-news-content"> |
||||
<h3>{item.title}</h3> |
||||
<p>{item.desc}</p> |
||||
</div> |
||||
|
||||
<div className="main-news-arrow">↗</div> |
||||
</article> |
||||
))} |
||||
</div> |
||||
</div> |
||||
</section> |
||||
); |
||||
} |
||||
|
||||
export default MainNews; |
||||
Loading…
Reference in new issue