You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
138 lines
4.8 KiB
138 lines
4.8 KiB
import { useEffect, useRef } from "react"; |
|
import { gsap } from "gsap"; |
|
import { ScrollTrigger } from "gsap/ScrollTrigger"; |
|
|
|
gsap.registerPlugin(ScrollTrigger); |
|
|
|
function MainVisual() { |
|
const sectionRef = useRef(null); |
|
const bgRef = useRef(null); |
|
const hero2Ref = useRef(null); |
|
const videoRef = useRef(null); |
|
const text1Ref = useRef(null); |
|
const text2Ref = useRef(null); |
|
const progressBarRef = useRef(null); |
|
|
|
useEffect(() => { |
|
const ctx = gsap.context(() => { |
|
const videoEl = videoRef.current; |
|
|
|
if (videoEl) { |
|
videoEl.pause(); |
|
videoEl.currentTime = 0; |
|
} |
|
|
|
gsap.set(hero2Ref.current, { opacity: 0, scale: 1.12, filter: "blur(12px)" }); |
|
|
|
gsap.set(text2Ref.current, { |
|
opacity: 0, |
|
y: 54, |
|
x: 0, |
|
scale: 0.965, |
|
filter: "blur(10px)", |
|
}); |
|
|
|
gsap.set(progressBarRef.current, { width: "0%" }); |
|
gsap.set(".fill-line", { backgroundPosition: "100% 0%" }); |
|
|
|
const darkHeroTrigger = ScrollTrigger.create({ |
|
trigger: sectionRef.current, |
|
start: "top top", |
|
end: "+=3000", |
|
onEnter: () => document.body.classList.add("is-dark-hero"), |
|
onEnterBack: () => document.body.classList.add("is-dark-hero"), |
|
onLeave: () => document.body.classList.remove("is-dark-hero"), |
|
onLeaveBack: () => document.body.classList.remove("is-dark-hero"), |
|
}); |
|
|
|
let hero2Started = false; |
|
|
|
const tl = gsap.timeline({ |
|
scrollTrigger: { |
|
trigger: sectionRef.current, |
|
start: "top top", |
|
end: "+=3000", |
|
scrub: 1.15, |
|
pin: true, |
|
anticipatePin: 1, |
|
onUpdate: (self) => { |
|
gsap.set(progressBarRef.current, { width: `${self.progress * 100}%` }); |
|
|
|
if (!videoEl) return; |
|
|
|
if (self.progress >= 0.42 && !hero2Started) { |
|
hero2Started = true; |
|
videoEl.currentTime = 0; |
|
videoEl.play().catch(() => {}); |
|
} |
|
|
|
if (self.progress < 0.42 && hero2Started) { |
|
hero2Started = false; |
|
videoEl.pause(); |
|
videoEl.currentTime = 0; |
|
} |
|
}, |
|
}, |
|
}); |
|
|
|
tl.to(bgRef.current, { width: "100vw", height: "100vh", borderRadius: 0, ease: "none" }, 0).to(bgRef.current, { scale: 1.08, ease: "none" }, 0).to(".fill-line", { backgroundPosition: "0% 0%", ease: "none", stagger: 0.14, duration: 1.35 }, 0.1).to(hero2Ref.current, { opacity: 1, scale: 1.035, filter: "blur(0px)", ease: "none" }, 1.55).to(text1Ref.current, { opacity: 0, y: -34, scale: 0.985, filter: "blur(8px)", ease: "none" }, 1.78).to(text2Ref.current, { opacity: 1, y: 0, scale: 1, filter: "blur(0px)", ease: "none" }, 1.95).to(hero2Ref.current, { scale: 1.095, ease: "none" }, 2.5); |
|
|
|
return () => { |
|
if (videoEl) { |
|
videoEl.pause(); |
|
videoEl.currentTime = 0; |
|
} |
|
darkHeroTrigger.kill(); |
|
document.body.classList.remove("is-dark-hero"); |
|
}; |
|
}, sectionRef); |
|
|
|
return () => ctx.revert(); |
|
}, []); |
|
return ( |
|
<section className="main-section" ref={sectionRef}> |
|
<div className="main-bg-wrap"> |
|
<div className="main-bg" ref={bgRef}> |
|
<div className="main-bg-hero1"></div> |
|
|
|
<div className="main-bg-hero2" ref={hero2Ref}> |
|
<video ref={videoRef} className="hero-video" src="./images/test.mp4" muted loop playsInline preload="auto" /> |
|
</div> |
|
|
|
<div className="main-visible-atmo main-visible-atmo1"></div> |
|
<div className="main-visible-atmo main-visible-atmo2"></div> |
|
<div className="main-visible-beam main-visible-beam1"></div> |
|
<div className="main-visible-beam main-visible-beam2"></div> |
|
<div className="main-visible-haze"></div> |
|
<div className="main-grid"></div> |
|
|
|
<div className="main-text"> |
|
<div className="text text-fill text-left-bottom" ref={text1Ref}> |
|
<span className="main-kicker">PAL NETWORKS</span> |
|
<span className="fill-line">Technology Partner for</span> |
|
<br /> |
|
<span className="fill-line">Advanced Air Mobility</span> |
|
</div> |
|
|
|
<div className="text text-change text-center-hero" ref={text2Ref}> |
|
항공 데이터와 통합 관제 기술로 |
|
<br /> |
|
안전한 하늘길을 설계합니다 |
|
</div> |
|
</div> |
|
|
|
<div className="main-progress"> |
|
<span className="main-progress-bar" ref={progressBarRef}></span> |
|
</div> |
|
|
|
<div className="main-scroll-indicator"> |
|
<span className="main-scroll-line"></span> |
|
<span className="main-scroll-text">SCROLL</span> |
|
</div> |
|
</div> |
|
</div> |
|
</section> |
|
); |
|
} |
|
|
|
export default MainVisual;
|
|
|