dwook.record
Published on

Intersection Observer를 이용한 Scroll 애니메이션

Authors
  • avatar
    Name
    dwook

Instersection Observer

  • 이전에는 scrollTop, getBoundingClientRect() 등을 사용

  • 이전 스크롤 이벤트의 문제점

    • 스크롤을 하면 다수의 스크롤 이벤트 발생. debounce등의 작업 필요.
    • getBoundingClientRect() 호출 시 리플로우 작업으로 성능저하 발생
  • polyfill을 사용해야하나 모던 웹브라우저 대부분은 지원

  • 타겟과, 타겟의 부모나 뷰포트가 교차하는 부분의 변화를 비동기로 관찰하는 API

  • 메인스레드에서 계속 교차를 확인하는 대신 교차가 일어날 때 인자로 넘겨준 콜백함수를 실행

  • 옵션

    • root: 타겟이 보이는지 결정하는 타켓의 부모 또는 뷰포트. 타겟의 상위 엘리먼트여야 하고 기본값은 브라우저의 뷰포트.
    • rootmargin: root의 margin으로 사용할 값. 기본값은 0이고, px나 %.
    • threshold: 타겟이 얼만큼 보여야 콜백함수를 실행할지 결정하는 값. number 또는 array. 0.3는 타겟이 30% 노출되었을 때 이벤트 실행. array는 각각의 비율로 노출될 때마다 함수가 실행.

기본

html
<div class="animation" data-delay="0s">
<div class="animation" data-delay=".5s">
<div class="animation" data-delay=".7s">
<div class="animation" data-delay="1s">
css
.animation {
  opacity: 0; /* 0으로 시작해야 없다가 나타나는 형태 */
}

@keyframes animation {
  from {
    transform: translateY(-100px);
    opacity: 0;
  }
  to  {
    transform: translateY(0);
    opacity: 1;
  }
}
js
// 애니메이션 요소 1개
const target = document.querySelector('.animation');

// 1단계: observer 인스턴스 생성
const observer = new IntersectionObserver((entries) => {
  if(entries[0].intersectionRatio > 0) {
    entries[0].target.style.animation = `animation 2s forwards ease-out`;
  } else {
    entries[0].target.style.animation = 'none';
  }
}, options);

// 2단계: observe 메서드에 target을 넘김.
observer.observe(target);
js
// 애니메이션 요소 여러개
const targetList = document.querySelectorAll('.animation');

const bserver = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if(entry.intersectionRatio > 0) {
      entry.target.style.animation = `animation 2s ${entry.target.dataset.delay} forwards ease-out`;
    }
    else {
      entry.target.style.animation = 'none';
    }
  })
}, options);

targetList.forEach(target => {
    observer.observe(target)
});

Hook


참조링크