<aside> ✋
“페이지를 스크롤하면, 그에 맞춰 영상이 같이 움직이게 해 주세요.“
</aside>
최근에 스크롤에 따라 영상 타임라인이 동기화되는 인터랙션 구현 요청이 있었다. 이번 문서에서는 페이 지를 스크롤할 때마다 영상의 재생 위치를 동기화하는 스크롤 기반 비디오 컨트롤에 대해 소개한다.
let isVideoLoaded = false;
const scrollToTimeRatio = 350;
const videoElement = document.querySelector('#video_container .video');
const videoContainer = document.getElementById('video_container');
let lastScrollTime = 0;
const throttleDelay = 100;
isVideoLoaded : 영상이 로드되었는지 여부를 판단한다.
중복 초기화를 방지하기 위해 사용한다.scrollToTimeRatio : 스크롤 위치와 영상 재생 시간 간의 비율.
값이 350인 경우, 스크롤을 350px 내릴 때 영상이 1초 재생. 값이 클수록 천천히 재생된다.videoElement : 제어 대상이 되는 요소.videoContainer : 비디오를 감싸는 컨테이너 요소. 위치 계산에 사용된다.const play = () => {
const scrollPosition = Math.max(0, window.scrollY - videoContainer.offsetTop);
videoElement.currentTime = scrollPosition / scrollToTimeRatio;
};
scrollY )에서 videoContainer 의 상단 위치( offsetTop )를 빼서
비디오 컨테이너 내부에서 얼마나 스크롤했는지를 계산한다.scrollToTimeRatio 로 나누어 해당 위치에 맞는
비디오 시간( currentTime )으로 바꾼다.Math.max(0, ...) 을 사용하여 currentTime 이 음수가 되는 것을 방지한다.const throttleScroll = () => {
const currentTime = performance.now();
if (currentTime - lastScrollTime >= throttleDelay) {
lastScrollTime = currentTime;
window.requestAnimationFrame(play);
}
};
scroll 이벤트는 매우 자주 발생하므로, 일정 간격( throttleDelay )으로만 처리하도록 제한한다.performance.now() 를 이용해 마지막 실행 시간과 현재 시간을 비교하고,
설정된 시간( throttleDelay ) 이상 경과했을 때만 실행되도록 제어한다.requestAnimationFrame 을 이용해서 브라우저 렌더링 타이밍에 맞춰 실행한다.
이렇게 하면 화면 깜빡임 없이 부드럽게 처리되어 성능이 개선된다.