반응형
PARD 동아리 웹사이트를 만들면서 웹사이트 HomePage에 처음 딱 들어왔을 때 동영상으로 이루어진 배경화면을 스크롤 제어를 통해 마치 스크롤에 따른 애니메이션 기능을 구현하고자 아래와 같은 코드를 짜봤다.
GSAP(GreenSock Animation Platform)라는 라이브러리를 통해 웹 애니메이션을 구현하고자 하였다.
gsap.to(window, {}) 를 통해 동영상의 재생과 정지를 스크롤에 따라 제어하였으며, window.pageYOffset; 를 활용하여 현재 스크롤 위치 정보를 저장하였다. videoPRogress를 계산하여 스크롤 값에 따라 비디오의 정지 포인트를 관리하였다.
아래는 내가 기능 구현을 위해 짜보았던 코드이다.
import React, { useRef, useEffect } from 'react';
import { gsap } from 'gsap';
function HomeVideo() {
const videoRef = useRef(null); // 비디오 요소를 참조하기 위한 useRef
const blueScreenRef = useRef(null); // 파란 배경 요소를 참조하기 위한 useRef
const isPlayingRef = useRef(false); // 비디오 재생 여부를 저장하기 위한 useRef
const lastScrollTimeRef = useRef(Date.now()); // 마지막 스크롤 시간을 저장하기 위한 useRef
useEffect(() => {
const video = videoRef.current; // 비디오 요소
const blueScreen = blueScreenRef.current; // 파란 배경 요소
const playVideo = () => {
video.play(); // 비디오 재생
isPlayingRef.current = true; // isPlayingRef를 true로 설정하여 비디오가 재생 중임을 표시
};
const pauseVideo = () => {
video.pause(); // 비디오 일시 정지
isPlayingRef.current = false; // isPlayingRef를 false로 설정하여 비디오가 일시 정지 중임을 표시
};
const updateVideoTime = () => {
const scrollPosition = window.pageYOffset; // 현재 스크롤 위치
const videoOffsetTop = video.offsetTop; // 비디오 요소의 페이지에서의 상단 위치
const videoHeight = video.offsetHeight; // 비디오 요소의 높이
if (video.readyState >= 2) {
const videoProgress = (scrollPosition - videoOffsetTop) / (videoHeight * 38); // 스크롤 위치에 따른 비디오 진행도 계산
const currentTime = video.duration * videoProgress; // 비디오의 현재 시간 계산
video.currentTime = currentTime; // 비디오의 현재 시간을 업데이트
}
};
const handleScroll = () => {
const now = Date.now(); // 현재 시간
const timeSinceLastScroll = now - lastScrollTimeRef.current; // 마지막 스크롤 이후의 시간 차이 계산
updateVideoTime(); // 스크롤에 따른 비디오 시간 업데이트
if (timeSinceLastScroll > 1 && isPlayingRef.current) {
pauseVideo(); // 일정 시간 이후에 비디오가 재생 중이면 일시 정지
}
lastScrollTimeRef.current = now; // 마지막 스크롤 시간 업데이트
};
window.addEventListener('scroll', handleScroll); // 스크롤 이벤트 리스너 등록
gsap.to(window, {
scrollTrigger: {
trigger: video,
start: 'top top',
end: 'bottom bottom',
onEnter: playVideo, // 스크롤 영역에 진입할 때 비디오 재생
onLeave: pauseVideo, // 스크롤 영역을 벗어날 때 비디오 일시 정지
onEnterBack: playVideo, // 스크롤 영역에 다시 진입할 때 비디오 재생
onLeaveBack: pauseVideo, // 스크롤 영역을 다시 벗어날 때 비디오 일시 정지
},
});
video.addEventListener('ended', () => { // 영상이 끝났을 떄 파랑 화면으로 이동
gsap.to(window, {
duration: 1,
scrollTo: {
y: blueScreen,
offsetY: 80,
},
});
});
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);
return (
<div >
<div style={{ height: '39000px' }}>
{/* 33800px' */}
</div>
<video
ref={videoRef}
src={require('../../../assets/Video/BackGround_Video.mp4')}
muted
quality="high"
loop
style={{ position: 'fixed', top: 0, left: 0, width: '100%', height: '100%', objectFit: "fill", zIndex: -1 }}
onLoadedMetadata={() => {
console.log('Video duration:', videoRef.current.duration);
}}
/>
</div>
);
};
export default HomeVideo;
반응형
'코딩 > React' 카테고리의 다른 글
[React] 배경화면 동영상/사진 - Safari 자동재생 안됨, Chrome 구분하여 자동재생 작동하기 구현 (0) | 2023.07.07 |
---|---|
[React] date-fns와 Style-Components로 커스텀하기 쉬운 달력 만들기(2편) (0) | 2023.07.06 |
[React] date-fns와 style-components로 커스텀하기 쉬운 달력 만들기(1편) (2) | 2023.07.06 |
[React] 웹 배포하기 전 Index.html에 콘텐츠 설명(OG 태그) 넣어주기. (1) | 2023.06.07 |
[React] Firebase CRUD 다양한 예시 코드! (0) | 2023.06.07 |