Intersection Observer API

seul gi lee·2020년 10월 15일
0
post-thumbnail

infinite scroll을 구현(지정된 개수의 컨텐츠만큼 스크롤이 끝에 도달하면 다음 컨텐츠를 로딩)하려던 중 발견한 Intersection Observer API..!

1. Intersection Observer API?

아래는 MDN에서 Intersection Observer API의 설명이다.

Intersection Observer API는 타겟 요소와 상위 요소 또는 최상위 document 의 viewport 사이의 intersection 내의 변화를 비동기적으로 관찰하는 방법입니다.

사실 window scroll event로 구현할 수 있지만 scroll event로 구현하게 되면 매번 발생되는 이벤트로 인해 성능이 저하된다고 알고있다..!

infinite-scroll의 동작과 비교하며 아래와 같이 설명하고 있다.

Intersection Observer API 는 그들이 감시하고자 하는 요소가 다른 요소(viewport)에 들어가거나 나갈때 또는 요청한 부분만큼 두 요소의 교차부분이 변경될 때 마다 실행될 콜백 함수를 등록할 수 있게 합니다. 즉, 사이트는 요소의 교차를 지켜보기 위해 메인 스레드를 사용할 필요가 없어지고 브라우저는 원하는 대로 교차 영역 관리를 최적화 할 수 있습니다.

2. 동작

Intersection Observer API의 동작 흐름은 관찰될 대상을 지정하여 옵션으로 설정한 대상의 intersection ratio(가시성 퍼센티지)만큼 대상이 보였을 때 콜백으로 설정한 함수가 실행됩니다.
=> root로 설정된 요소와 대상으로 설정된 요소가 퍼센티지만큼 교차됐을 때 콜백이 실행된다.

let options = {
  root: document.querySelector('#scrollArea'), // 태그의 id가 scrollArea인 요소를 뷰포트로 지정
  rootMargin: '0px', // root 가 가진 여백
  threshold: 1.0 // 대상 요소가 root 에 지정된 요소 내에서 100% 보여질 때 콜백이 호출될 것을 의미
}

let observer = new IntersectionObserver(callback, options); // 여기서 옵션은 observer 콜백이 호출되는 상황을 조작할 수 있습니다.

위의 options의 속성에 대한 설명입니다.

  • root : 대상 객체의 가시성을 확인할 때 사용되는 뷰포트 요소. default는 브라우저 뷰포트. null 또는 지정되지 않을 때 기본으로 설정된다.
  • rootMargin : root 가 가진 여백. CSS의 margin 속성과 유사. 이것은 root 요소의 각 측면의 bounding box를 수축시키거나 증가시키며, 교차성을 계산하기 전에 적용됩니다. default는 0입니다.
  • threshold : observer의 콜백이 실행될 대상 요소의 가시성 퍼센티지를 나타내는 단일 숫자 혹은 숫자 배열. 만일 타겟이 50%정도 나타났을 때를 탐지하고 싶다면, 값을 0.5로 설정하면 된다. 혹은 25% 단위로 요소의 가시성이 변경될 때마다 콜백이 실행되게 하고 싶다면 [0, 0.25, 0.5, 0.75, 1] 과 같은 배열을 설정하면 된다.
    기본값은 0이며(이는 요소가 1픽셀이라도 보이자 마자 콜백이 실행됨을 의미). 1.0은 요소의 모든 픽셀이 화면에 노출되기 전에는 콜백을 실행시키지 않음을 의미한다.

3. 사용 예제

아래와 같은 상황에서 사용할 수 있습니다.

  • 페이지가 스크롤 되는 도중에 발생하는 이미지나 다른 컨텐츠의 지연 로딩.
  • 스크롤 시에, 더 많은 컨텐츠가 로드 및 렌더링되어 사용자가 페이지를 이동하지 않아도 되게 하는 infinite-scroll 을 구현.
  • 광고 수익을 계산하기 위한 용도로 광고의 가시성 보고.
  • 사용자에게 결과가 표시되는 여부에 따라 작업이나 애니메이션을 수행할 지 여부를 결정.
let target = document.querySelector('#listItem');

let options = {
  root: null,
  rootMargin: "0px",
  threshold: 1,
};

let observer = new IntersectionObserver(callback, options);

observer.observe(target); // observe 될 타켓 등록

let callback = (entries, observer) => {
  // entries     - 등록된 타겟 목록
  // observer    - intersection observer 요소
  entries.forEach(entry => {
    //   entry.boundingClientRect   - Element.getBoundingClientRect()
    //   entry.intersectionRatio    - 노출 퍼센트
    //   entry.intersectionRect     - 노출된 영역
    //   entry.isIntersecting       - 노출 여부
    //   entry.rootBounds           - RootElement의 bound 값 만약 옵션에서 지정하지 않았다면, 화면 크기 이다.
    //   entry.target               - 타겟 요소
    //   entry.time                 - 노출되거나 비노출된 시간
    if (entry.isIntersecting) {
      // 화면에 options에서 지정한 threshold 퍼센트 만큼 노출됨
      observer.unobserve(entry.target); // 기존에 observe 되어있던 타겟 삭제
    }
  });
};


브라우저 호환 체크


[참고]

profile
백설 집사의 개발블로그입니다. :D

0개의 댓글