Intersection Observer APIを使って、ページの最下部までスクロールしたかを判定する

こんにちは、ナカムラです。
前回はスクロール量を計測して、ページの最下部までスクロールしたかを判定する処理をご紹介しました。今回は方法を変えて、Intersection Observer APIを使った場合の処理について書いていきたいと思います。

前回の記事はこちら

tech.arms-soft.co.jp

Intersection Observer APIとは?

Intersection Observer API - Web API | MDN

Intersection Observer API (交差監視 API) は、ターゲットとなる要素が、祖先要素もしくは文書の最上位のビューポートと交差する変更を非同期的に監視する方法を提供します。

と書かれています。
ビューポートは表示領域のことなので、ブラウザの表示領域という認識でよいかと思います。
ブラウザの表示領域を超えるサイズの場合にスクロールが発生します。
スクロールした際に、ターゲットとなる要素が「ビューポートと交差した=表示された」かどうかを監視してくれる仕組みです。
前回のようにスクロール量を常に取得し、比較する処理がなくなるので、こちらの方がパフォーマンスも良いです。

※IEは非対応なため、polyfillを読み込む必要があります。
(DEMOはCodePenで書いているので、IEでは確認できませんが、ちゃんと機能しました)
IntersectionObserver/polyfill at main · w3c/IntersectionObserver · GitHub

DEMO

See the Pen Intersection Observer APIを使って、ページの最下部までスクロールしたかを判定する_blog用 by Nakamura (@takayo-nakamura) on CodePen.

大きく3つに分けて紹介します。
・ターゲットの設定
・ターゲットを監視する
・交差した時に実行する処理

ターゲットの設定

まずは監視対象になる要素と、オプションを設定していきます。

交差を監視したい要素

classに'js-intersection'を持っている要素を監視したいので、querySelectorAllで取得します。

オプションの設定

const intersectptions = {
  root: null,
  rootMargin: '0px',
  threshold: 0
}

root

ターゲットが見えるかどうかを確認するためのビューポートとして使用される要素です。
ブラウザのビューポートで良い場合はnullにします。

rootMargin

root の周りのマージンです。
'0px'は要素の開始位置になります。
交差したと判定するポイントをずらしたい時に数値を設定します。

threshold

閾値になります。
交差してからどのくらいの割合で検出するかの設定になります。
0:1ピクセルでも表示されたらコールバックを実行します。
0.25:25%表示されたらコールバックを実行します。

ターゲットを監視する

IntersectionObserverを作成

IntersectionObserver()の 第一引数にコールバック関数(交差した時に実行したい関数)、
第二引数にオプションを書きます。

const observer = new IntersectionObserver(itemIntersect, intersectptions)

監視する

observe()メソッドを使い、
作成したobserverに、監視対象のターゲットを渡します。

itemsList.forEach(item => {
  observer.observe(item)
})

これでオプションの条件を満たすたびにコールバック関数が実行されます。

交差した時に実行する処理

ここまできたら後は実行したい処理を書いていけば完成です。
見えている時にクラス'is-active'を付与し、
見えなくなったら付与したクラスをはずす、という処理を書きます。

IntersectionObserverEntry オブジェクトのプロパティ値を使って判定します。
見えている時はisIntersectingがtureの時になります。
tureの時はクラスを付与し、falseの時はクラスを削除します。

※その他のプロパティについてはこちら
IntersectionObserverEntry - Web APIs | MDN

function itemIntersect (entries) {
  entries.forEach((entry) => {
    if (entry.isIntersecting) {
      entry.target.classList.add('is-active')
    } else {
      entry.target.classList.remove('is-active')
    }
  })
}

あとは付与されたクラスにCSSを当てていけば完成です。

まとめ

今回のDEMOではセクションとpage topボタンの交差を監視しています。
footerにもターゲットとなる'js-intersection'をつけたので、
footerが表示された=ページの最下部までスクロールしたという判定処理になりました。

javascriptの処理はひとつですが、
要素に合わせたCSSでそれぞれに別々の動きをつけることができますので、
いろいろな見せ方をつけることができます。
CSSの組み合わせもいろいろ試してみてください。

参考

こちらの記事を参考にさせていただきました。
JSでのスクロール連動エフェクトにはIntersection Observerが便利 - ICS MEDIA Intersection Observer API - Web API | MDN