👻

Intersection Observer APIの使い方

2024/12/19に公開

Intersection Observer APIとは

  • 要素がビューポートまたは特定のコンテナ内に入ったり出たりするタイミングを非同期的に監視するためのAPI
  • スクロールイベントの監視、ビューポートの交差を利用するタスクの処理が可能

Intersection Observer APIの使い方の例

前提条件(やりたいこと)

下記のようにhiddenというクラスがついたh2要素がある
この要素がビューポートに交差したら、要素が表示されるようにしたい
fade-in-upというクラスをつけたい)

<h2 class="hidden">hogehoge</h2>
@keyframes fadeInUp {
    0% {
        opacity: 0;
        transform: translateY(20px);
    }

    100% {
        opacity: 1;
        transform: translateY(0);
    }
}

.hidden {
    opacity: 0;
}

.fade-in-up {
    opacity: 0;
    animation: fadeInUp 1s ease-out forwards;
}

IntersectionObserver使い方

  1. IntersectionObserver オブジェクトを生成する
const observer = new IntersectionObserver( callback [, options] );
  • callback
    • optionsのthreshold に指定したタイミングで呼び出される
  • options
    • root: nullの場合、ビューポートが基準
    • rootMargin: ビューポートのマージンを設定
    • threshold: 監視対象の要素がビューポートにどの程度交差したら交差を検知するか
  1. observe() で要素を監視
//監視する対象の要素を取得(直接 observe() メソッドの引数に指定可能)
const hogehoge = document.querySelector('.hogehoge');
//対象の要素をオブジェクトの observe() メソッドに指定
observer.observe(hogehoge);

実際のコード

window.addEventListener('load', function () {
    var observerOptions = {
        root: null,
        rootMargin: '0px 0px -20% 0px',
        threshold: 0
    };
    var observer = new IntersectionObserver(function (entries, observer) {
        entries.forEach(function (entry) {
//entry.isIntersecting: 要素がビューポートに入っているかどうかを示すブール値
            if (entry.isIntersecting) {
                if (entry.target.classList.contains('hidden')) {
                    entry.target.classList.add('fade-in-up');
                    entry.target.classList.remove('hidden');
                }
            } else {
                if (entry.target.classList.contains('fade-in-up')) {
                    entry.target.classList.remove('fade-in-up');
                    entry.target.classList.add('hidden');
                }
            }
        });
    }, observerOptions);
    document.querySelectorAll('.hidden').forEach(
        function (element) {
            observer.observe(element);
        });
});

Discussion