본문 바로가기
UX 개발/UX - 스크롤 애니메이션

스크롤 이벤트에 따른 동영상 재생 애니메이션 만들기

반응형

 

 

웹 페이지에 스크롤 이벤트를 사용하여 동영상을 애니메이션하는 것은 사용자 경험을 더욱 풍부하게 만들 수 있는 훌륭한 방법입니다. 이번 포스트에서는 스크롤 이벤트에 따라 동영상이 재생되고 애니메이션되는 웹 페이지를 만드는 방법을 소개합니다. 예제 코드를 통해 이 과정을 자세히 설명하겠습니다.

HTML 및 CSS 설정하기

먼저 HTML 구조를 설정하고 CSS 파일을 링크합니다. 아래는 HTML 코드입니다:

<!DOCTYPE html>
<html lang="ko">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="./index.css">
  <title>Fast Bank</title>
</head>

<body>

  <main>
    <div id="margin-area">
      <div class="page-title">Scroll for Movie Frame Animation</div>
    </div>
    <section id="video-section">
      <div id="fixed-wrapper">
        <video id="video" src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4" type="video/mp4" muted loop></video>
        <div id="fixed-description">
          <div>The Video</div>
          <div>Ends Here.</div>
        </div>
      </div>
    </section>
  </main>
</body>

<script src="index.js"></script>

</html>

이 구조에서 우리는 스크롤 시 동영상이 재생되는 video 요소를 포함하는 메인 섹션을 가지고 있습니다. 이제 CSS를 사용하여 요소들을 스타일링하고 애니메이션을 정의해보겠습니다.

CSS로 스타일링 및 애니메이션 적용하기

CSS 파일에는 본문, 메인 이미지 래퍼, 소개 텍스트, 동영상 요소에 대한 스타일이 포함됩니다. 아래는 CSS 코드입니다:

body {
  background-color: #111111;
}

#main-img-wrapper {
  padding-top: 139px;
  text-align: center;
}

#intro-main {
  display: flex;
  flex-direction: column;
  margin: 54px auto 140px;
  width: 300px;
  align-items: center;
  color: white;
  font-size: 40px;
  font-weight: 500;
  gap: 20px;
}

#join-us-text {
  margin-top: 73px;
  font-size: 16px;
  font-weight: 400;
  opacity: .6;
}

#intro-main p {
  text-align: center;
}

@keyframes upAndDown {
  0% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-10px);
  }
  100% {
    transform: translateY(0);
  }
}

#down-arrow-icon {
  width: 33px;
  animation: upAndDown 1s infinite;
}

#list-item-wrapper {
  margin: 0 auto 500px;
  width: 383px;
}

.list-item {
  display: inline;
  font-size: 48px;
  font-weight: 600;
}

.list-item::before {
  display: inline-block;
  background-image: url('./icons/dark_house.png');
  background-size: 51px 53px;
  content: "";
  width: 51px;
  height: 53px;
}

.list-item#on {
  color: white;
}

.list-item#on::before {
  background-image: url('./icons/light_house.png');
}

#panel1-img {
  overflow: hidden;
  margin-bottom: 500px;
  position: relative;
  height: 320px;
}

#flying-santa-image {
  position: absolute;
  right: -80px;
  height: 310px;
  transform: translate(80px, -13px) rotate(23deg);
}

#video-section {
  margin-bottom: 1000px;
}

#video {
  display: block;
  margin: 0 auto;
  height: 350px;
}

#fixed-description {
  width: 622px;
  margin: 30px auto 0;
  color: white;
  text-align: right;
  line-height: 50px;
  font-size: 35px;
  font-weight: 600;
  transform: translateY(100px);
  opacity: 0;
}

#margin-area {
  height: 1585px;
}

.page-title {
  color: #fff;
  font-size: 40px;
  text-align: center;
  padding: 20px 0;
  font-weight: bold;
}

CSS의 주요 포인트

  • 본문 배경: 다른 요소들과 강렬한 대비를 주기 위해 어두운 색상으로 설정.
  • 동영상 섹션: 동영상과 설명 텍스트를 중앙에 배치.
  • 애니메이션 키프레임: 상하 움직임을 정의하는 @keyframes 규칙.
  • 설명 텍스트: 스크롤에 따라 위치와 불투명도가 변하는 스타일 적용.

JavaScript로 스크롤 애니메이션 추가하기

스크롤 이벤트에 따라 동영상이 재생되고 설명 텍스트가 애니메이션되도록 하기 위해 JavaScript를 사용합니다. 아래는 JavaScript 코드입니다:

document.addEventListener('DOMContentLoaded', function() {
  const videoPlayBack = 360;

  const videoElement = document.getElementById('video');
  const videoSection = document.getElementById('video-section');

  const fixedWrapper = document.getElementById('fixed-wrapper');
  const fixedDescription = document.getElementById('fixed-description');

  function centerElement(elementId, video) {
    const element = document.getElementById(elementId);
    const parent = element.parentElement;

    if (window.scrollY > parent.offsetTop - ((document.documentElement.clientHeight - element.offsetHeight) / 2)) {
      element.style.position = 'fixed';
      element.style.top = '50%';
      element.style.left = '50%';
      element.style.transform = 'translate(-50%, -50%)';

      if (video) {
        video.currentTime = (window.scrollY - videoSection.offsetTop) / videoPlayBack;
      }
    } else {
      element.style.position = 'relative';
      element.style.top = 'initial';
      element.style.left = 'initial';
      element.style.transform = 'initial';
    }
  }

  videoElement.addEventListener('loadedmetadata', function() {
    document.getElementById('video-section').style.height = videoElement.duration * videoPlayBack + 'px';
  });

  const fixedDescriptionAppearTiming = 3470;
  const fixedDescriptionAppearEnds = 3800;

  window.addEventListener('scroll', function() {
    const scrollYBottom = window.scrollY + document.documentElement.clientHeight;

    centerElement("fixed-wrapper", videoElement);

    if (window.scrollY > videoSection.offsetTop + videoSection.offsetHeight - (fixedWrapper.offsetHeight + (document.documentElement.clientHeight - fixedWrapper.offsetHeight) / 2)) {
      fixedWrapper.style.position = 'relative';
      fixedWrapper.style.top = 'initial';
      fixedWrapper.style.left = 'initial';
      fixedWrapper.style.transform = `translateY(${videoSection.offsetHeight - fixedWrapper.offsetHeight}px)`;
    }

    if (window.scrollY > fixedDescriptionAppearTiming && window.scrollY < fixedDescriptionAppearEnds) {
      fixedDescription.style.transform = `translateY(${fixedDescriptionAppearEnds - window.scrollY}px)`;
      fixedDescription.style.opacity = (window.scrollY - fixedDescriptionAppearTiming) / 300;
    } else if (window.scrollY > fixedDescriptionAppearEnds) {
      fixedDescription.style.transform = `translateY(0px)`;
      fixedDescription.style.opacity = 1;
    } else {
      fixedDescription.style.transform = `translateY(100px)`;
      fixedDescription.style.opacity = 0;
    }
  });
});

JavaScript 설명

  • 이벤트 리스너: DOMContentLoaded 이벤트를 감지하여 DOM이 완전히 로드된 후 스크립트를 실행.
  • 중앙 요소 고정 함수: 요소가 부모 요소의 상단에 가까워지면 화면 중앙에 고정되도록 위치를 조정.
  • 스크롤 이벤트: 스크롤 이벤트를 감지하여 동영상 재생 시간과 설명 텍스트의 위치 및 불투명도를 조정.
  • 메타데이터 로드 이벤트: 동영상의 메타데이터가 로드되면 동영상 섹션의 높이를 동영상 재생 시간에 맞게 설정.

결론

스크롤 이벤트를 사용하여 동영상을 애니메이션하면 웹페이지의 상호작용성과 시각적 매력을 크게 향상시킬 수 있습니다. 이 튜토리얼에서는 스크롤 시 동영상이 재생되고 설명 텍스트가 애니메이션되는 예제를 보여드렸습니다. 다양한 애니메이션과 스타일을 실험하여 웹페이지를 더욱 동적이고 매력적으로 만들어 보세요.

반응형
❤️ 외주/과외 문의
🖥️ 클라우드 메뉴판 : 디지털팝