PORTFOLIO & WEB DESIGN MEMORANDOM BLOG   
PORTFOLIO & WEB DESIGN MEMORANDOM BLOG   

【JavaScript】IntersectionObserverって何?スクロール連動の仕掛けがカンタンに!

そもそもIntersectionObserverって?

簡単に言うと、「ある要素が、画面(または特定の親要素)の中に入ったかどうかを教えてくれる仕組み」です。

たとえばこんな場面、よくありませんか?
• 特定のセクションが画面に入ったらアニメーションを始めたい
• 無限スクロール(下にスクロールしたらコンテンツを自動で追加したい)
• ヘッダーの表示/非表示をスクロールに合わせて切り替えたい

そんなとき、昔はスクロールイベントを使って位置をゴリゴリ計算してましたが、今はIntersectionObserverでスマートになります!

使い方はとってもシンプル

まずは基本の構文から。

  1. const observer = new IntersectionObserver((entries, observer) => {
  2.   entries.forEach(entry => {
  3.     if (entry.isIntersecting) {
  4.       console.log('見えてるよ!', entry.target);
  5.     }
  6.   });
  7. });
  8. const target = document.querySelector('.watch-me');
  9. observer.observe(target);

このコードでやってることは:
1. IntersectionObserverを作成
2. .watch-meというクラスの要素を監視開始
3. 画面内にその要素が入ったタイミングでコールバックが発火!

オプションも指定できる

  1. const observer = new IntersectionObserver(callback, {
  2.   root: null, // 画面全体(デフォルト)
  3.   threshold: 0.5 // 50%表示されたら反応
  4. });

他にも、rootを指定すれば「この特定のスクロールエリア内で表示されたら反応」なんてこともできます。

ちょっとした例:スクロールでフェードイン

See the Pen
Untitled
by ryotom (@ryotam-smoke)
on CodePen.

これだけで、スクロールして表示されたらふわっと表示する仕掛けが完成です!

このコード、何をしているの?

ざっくり言うと、「.fade-inクラスが付いている要素を監視して、画面に入ったら.showクラスを追加する」という動きです。

IntersectionObserverで監視

  1. const observer = new IntersectionObserver((entries) => {
  2.   ...
  3. });

ここでは「画面に入ってきた要素を検出するためのオブザーバー(監視者)」を作っています。
• entriesは、監視している要素たちの状態(見えているかどうかなど)を配列で返してくれるものです。
• entry.isIntersecting は「今、要素が画面内に見えているかどうか」を true/false で教えてくれます。

要素が見えたら .show クラスを追加

  1. if (entry.isIntersecting) {
  2.   entry.target.classList.add('show');
  3. }

この部分で、「もし画面内に入ってきたら、show というクラスを追加してね」と命令しています。

つまり、CSS側で .show にアニメーションを設定しておけば、「画面に入った瞬間にアニメーションが始まる」というわけです!

.fade-inの要素たちを監視!

  1. document.querySelectorAll('.fade-in').forEach(el => observer.observe(el));

この一文で、
• .fade-in というクラスが付いているすべての要素を取得し、
• それぞれに対して observer.observe(el) を呼び出して、
• 一つずつ監視対象に登録しています。

※ el は 「element(エレメント)」の省略形で、HTMLの要素(=DOM要素)を指す変数名です。
この el という名前は実は何でもOKなんですが、element の略であることが多く、わかりやすいのでよく使われています。

スクロールで「見えてる?見えてない?」を表示してみよう!

以下のようなUIを作ります:
• スクロールしていくと出てくる要素(ここでは大きな #box)。
• それが画面に表示されたら、左上に「見えてます!」と表示。
• 画面から外れたら「見えません!」と切り替わる。

See the Pen
Untitled
by ryotom (@ryotam-smoke)
on CodePen.

「threshold」を用いてアニメ開始のタイミングを操ろう!

threshold(スレッショルド)は、IntersectionObserverの動作条件を決める「設定値(オプションプロパティ)」の一つです。
「どれくらい見えたら反応するか」を設定することが出来ます。
ざっくり言うと、対象の要素が画面(ビューポート)に何割見えたら処理を実行するかを決めるものです。

  1. { threshold: 0.3 }

と書いてある場合、「その要素が 30% 見えた時点で反応する」という意味になります。

0の場合1pxでも入ったら反応。0.5の場合は50%以上見えたら、
1.0は全体が完全に見えたら反応するというように、
「どのくらい出たら」の基準を数字で細かく決められるのが threshold なんです。

実際の使用例

  1. const observer = new IntersectionObserver((entries) => {
  2.   entries.forEach(entry => {
  3.     if (entry.isIntersecting) {
  4.       entry.target.classList.add('active');
  5.     } else {
  6.       entry.target.classList.remove('active');
  7.     }
  8.   });
  9. }, { threshold: 0.5 });
  10. document.querySelectorAll('.card').forEach(card => {
  11.   observer.observe(card);
  12. });

See the Pen
Untitled
by ryotom (@ryotam-smoke)
on CodePen.

このコードでは、監視している要素が半分以上表示されたらクラスが付与されます。

複数の閾値を配列で指定もできる!

  1. threshold: [0, 0.25, 0.5, 0.75, 1]

こうすると、それぞれの割合を通過するたびにイベントが発火します。
細かいアニメーションや、プログレスバーの実装などに使えます。

rootを使ってスクロール可能なdivの中で監視対象を設定

rootを指定することで、カスタムスクロール領域の中だけを監視対象にできます。
モーダル、タブ切り替え、横スクロールのギャラリーなどでも有用です。

See the Pen
Untitled
by ryotom (@ryotam-smoke)
on CodePen.

まとめ

IntersectionObserver を使えば、スクロールに合わせたインタラクションがとても簡単に実装できます。
パフォーマンスにも優しく、スクロールイベントよりスマートな選択肢です。

Webサイトやブログにちょっとしたリアクションを加えるとき、ぜひ活用してみてください!

MILMONA   MILMONA   MILMONA   MILMONA   MILMONA   
MILMONA   MILMONA   MILMONA   MILMONA   MILMONA