Intersection Observer APIを使う(JavaScript)

前書き

Intersection Observer APIの使い方を掲載しています。

目次

  1. Intersection Observer APIについて
  2. 交差しているかどうか
  3. どれくらい交差しているか
  4. 参考

Intersection Observer APIについて

要素とビューポート(もしくは祖先要素)の交差を監視する。
スクロールする度に実行されるスクロールイベントに比べて負荷が小さい。

交差しているかどうか

要素がビューポートと交差していたら表示する。
オプションには下記を指定している。
root:ビューポート
rootMargin:上下の値は-25%
threshold:0
要素が画面の上から、3/4、1/4まで来た時に実行される。

A
B

<div class="js-scroll-action js-scroll-action-a">A</div>
<div class="js-scroll-action js-scroll-action-b">B</div>

.js-scroll-action-a{
  //初め
    opacity: 0; transform: translateY(10px); transition: 1s;
  //クラスが付いたら
    &.is-intersecting{
      opacity: 1; transform: translateY(0px);
    }
}
.js-scroll-action-b{
  //初め
    opacity: 0; transform: translateX(10px); transition: 1s;
  //クラスが付いたら
    &.is-intersecting{
      opacity: 1; transform: translateX(0px);
    }
}

window.addEventListener("load", (event) => {
  //監視する要素を取得
  elements = document.querySelectorAll(".js-scroll-action");
  createObserver();
}, false);

function createObserver() {
  let observer;
  let options = {
    root: null, //null の場合はブラウザーのビューポート
    rootMargin: "-25% 0% -25% 0%", //rootの範囲を拡大、縮小出来る。単位必須(px,%)
    threshold: 0 //要素の、何割がrootと交差した時に実行するか。値は0~1。配列も指定可
  };
  //コールバック関数とオプションを渡す
  observer = new IntersectionObserver(handleIntersect, options);
  //要素の監視を開始
  elements.forEach((element) => {
    observer.observe(element);
  });
}

//コールバック関数
function handleIntersect(entries, observer) {
  entries.forEach((entry) => {
    //任意の関数
    itemDisp( entry.target, entry.isIntersecting );
    //entry.target 要素
    //entry.isIntersecting 交差しているかどうか
  });
}

//任意の関数
function itemDisp( entryTarget, entryIsIntersecting ){
  if(entryIsIntersecting){
    entryTarget.classList.add("is-intersecting");
  }else{
    entryTarget.classList.remove("is-intersecting");
  }
}

どれくらい交差しているか

要素がビューポートとどれくらい交差しているか、割合を表示する。
オプションには下記を指定している。
root:ビューポート
rootMargin:0%
threshold:0.0~1.0まで0.1刻み
その交差の割合が、thresholdで指定した値になった時に実行される。

A : -
B : -
C : -
A
B
C

<!-- 割合を表示する要素 -->
  <div>A : <span class="js-rate-disp-a"></span></div>
  <div>B : <span class="js-rate-disp-b"></span></div>
  <div>C : <span class="js-rate-disp-c"></span></div>
<!-- 監視する要素 -->
  <div class="js-rate-watch" data-watch="a">A</div>
  <div class="js-rate-watch" data-watch="b">B</div>
  <div class="js-rate-watch" data-watch="c">C</div>

window.addEventListener("load", (event) => {
  //監視する要素を取得
  elements02 = document.querySelectorAll(".js-rate-watch");
  createObserver02();
}, false);

function createObserver02() {
  let observer;
  let options = {
    root: null,
    rootMargin: "0%",
    threshold: buildThresholdList() //0.0~1.0まで0.1刻み
  };
  //コールバック関数とオプションを渡す
  observer = new IntersectionObserver(handleIntersect02, options);
  //要素の監視を開始
  elements02.forEach((element) => {
    observer.observe(element);
  });
}

//threshold
function buildThresholdList() {
  let thresholds = [];
  let numSteps = 10;
  for (let i=1.0; i<=numSteps; i++) {
    let ratio = i/numSteps;
    thresholds.push(ratio);
  }
  thresholds.push(0);
  return thresholds;
}

//コールバック関数
function handleIntersect02(entries, observer) {
  entries.forEach((entry) => {
    //任意の関数
    rateDisp( entry.target, entry.intersectionRatio );
    //entry.target 要素
    //entry.intersectionRatio どれくらい交差しているか
  });
}

//任意の関数
function rateDisp( entryTarget, entryIntersectionRatio ){
  //data属性を取得
  let watch = entryTarget.dataset.watch;
  document.querySelector(".js-rate-disp-" + watch ).textContent = entryIntersectionRatio;
}

参考

Intersection Observer API

JSでのスクロール連動エフェクトにはIntersection Observerが便利

Intersection Observer を用いた要素出現検出の最適化

関連記事

GSAP ScrollTriggerを使う(HTML/JS)

固定ヘッダの高さ分、スクロール位置をずらす(HTML/CSS)

先頭に戻る
ページの先頭に戻る