JavaScript

JavaScript로 Scroll Reveal Animation 구현하기

ea_jung 2024. 4. 29. 16:17

Next.js 로 프로젝트 중 토스 홈페이지를 보고 스크롤 이벤트 시 요소들이 여러 방향으로 나타나는 애니메이션을 프로젝트 소개 페이지(Intro Page)에 적용하고 싶었습니다. 그래서 React로 만들기에 앞서 JavaScript로 구현하여 원리를 파악하려 합니다. 다음 자료를 참고하여 구현해 보았습니다. 

✅  구현하고 싶은 내용

Scroll Reveal Animation를 적용하고 싶은 요소가 viewport에 들어왔을 때 애니메이션이 실행되게 하려고 합니다.

✅  transition, transform, animation

  • transition
    • transition: property duration timing-function delay;
    • transition은 hover나 onClick과 같은 이벤트 트리거에 의해 동작합니다.
    • 예시
div { 
    width: 100px; 
    height: 50px; 
    background-color: red; 
    margin-bottom: 10px; 
    transition-property: width, 
    background-color; /* 어떤 css 프로퍼티(width)를 transition할지 지정 */ 
    transition-duration: 2s, 2s; /* width와 bg-color가 2초동안 변화 */ 
}

div:hover { /* 마우스를 올리면 transition발동해서 적용될 상태 */
    width: 300px;
    background-color: blue;
}
  • transform
    • transform : scale(x,y) translate(x,y) rotate(deg) skew(xdeg,ydeg);
  • CSS animation
    • 애니메이션을 사용하면 트랜지션보다 화려한 css를 구현할 수 있습니다.
    • 트랜지션은 시작하기 위해 이벤트가 필요하지만 애니메이션은 시작, 정지, 반복까지 제어할 수 있습니다.
    • animation : @keyframes의 이름 animation-delay animation-duration animation-timing-function
      • animation-name: 키프레임 이름 (필수)
      • animation-iteration-count: 애니메이션 반복 횟수, infinite를 적어주면 무한반복 됩니다.
      • animation-direction: 애니메이션 방향으로 normal, reverse, alternate, alternate-reverse가 있습니다.
        • normal: 정방향
        • reverse: 역방향
        • alternate: 정방향 ➡️ 역방향 ➡️ 정방향 ... (alternate는 반복이 2이상 일 때부터 확인할 수 있습니다.)
        • alternate-reverse: 역방향 ➡️ 정방향 ➡️ 역방향...
      • animation-fill-mode: 애니메이션이 재생되지 않을 때 (애니메이션 시작 전(대기), 끝난 후(종료)) element의 스타일을 지정합니다.
        • none: 애니메이션 실행 전후 요소에 스타일 반영 x (애니메이션 종료 후 속성 값을 되돌림)
        • forwards: 마지막 키 프레임에서 설정한 스타일 값을 유지
        • backwards: 첫 번째 키 프레임(애니메이션 방향에 따라 다릅니다.)에 의해 설정된 스타일 값을 가져오고 애니메이션 지연 기간 동안 이를 유지
        • both: forwards, backwards를 모두 따름
@keyframes [키프레임 이름] {
  0%   {background-color:red; left:0px; top:0px;}
  25%  {background-color:yellow; left:200px; top:0px;}
  50%  {background-color:blue; left:200px; top:200px;}
  75%  {background-color:green; left:0px; top:200px;}
  100% {background-color:red; left:0px; top:0px;}
}

 

✅  getBoundingClientRect(), window.innerHeight() ,clientHeight() 을 이용하여 구현하기

 

el.getBoundingClientRect().top() 값과 document.document.clientHeight() (= 뷰포트 높이 값) 값을 이용해서 스크롤시 element가 나타나고 사라지는 순간을 포착하고, element가 viewport에 노출되는 순간 스타일(".js-scroll")을 추가해 애니메이션이 시작하게 하고, 끝나면 제거하는 방법으로 구현했습니다. IE8 이하 버전에서는 window.innerHeight가 지원되지 않기 때문에 window.innerHeight()를 이용한 조건도 함께 달아줄 수 있습니다.

 

 

const scrollElements = document.querySelectorAll('.js-scroll')

const elementInView = (el, dividend = 1) => {
  const elementTop = el.getBoundingClientRect().top

  // viewport 기준 element top이 보이기 시작할때는 감지한다.
  return (
    elementTop <=
    (window.innerHeight || document.documentElement.clientHeight / dividend) // dividend // 4/5 배
  )
}

// el가 viewport 아래로 사라질때를 감지한다.
const elementOutofView = (el) => {
  const elementTop = el.getBoundingClientRect().top

  return (
    elementTop > window.innerHeight || document.documentElement.clientHeight
  )
}

const displayScrollElement = (el) => {
  el.classList.add('scrolled')
}

const hideScrollElement = (el) => {
  el.classList.remove('scrolled')
}

const handleScrollAnimation = () => {
  scrollElements.forEach((el) => {
    if (elementInView(el, 1.25)) {
      displayScrollElement(el)
    } else if (elementOutofView(el)) {
      hideScrollElement(el)
    }
  })
}

window.addEventListener('scroll', () => {
  handleScrollAnimation()
})

 

 

✅  결과물

 

 

다음 게시물에서는 React로 구현해보고 애니메이션 실행 방향을 props으로 받아서 component로 만들어 보려고 합니다.

 

 

React로 Scroll Reveal Animation 구현하고 컴포넌트화 하기

<figure id="og_1714447333650" contenteditable="false" data-ke-type="opengraph" data-ke-align="alignCenter" data-og-type="article" data-og-title="JavaScript로 Scroll Reveal Animation 구현하기" data-og-description="Next.js 로 프로젝트 중 토스

dev-ea-jung.tistory.com

 

반응형