0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【JavaScript】Intersection Observerでスクロール処理をする

Last updated at Posted at 2023-02-11

やりたいこと

Intersection Observerをつかって要素連動の処理を実装する。

すでに、他のライブラリを読み込む数が多かったり、サイトの処理が重い場合などで、更に追加でGSAPなどを読み込むの敬遠される背景がある。

今回は、画面幅=ビューポート内に対象要素が入ってきたら文字色の変化を加える処理をする。

実装サンプル
アニメ.gif

※Codepenでは思ったタイミングでコールバック関数が発火してくれず、何か原因がわかる方いらっしゃれば教えて頂きたいです。。。

コード

const target = document.querySelector('.article__title--target');

//監視設定
const settings = 
  rootMargin: '-50% 0px',
  threshold: [0],
}

//IntersectionObserverコンストラクタでインスタンス化
const observer = new IntersectionObserver(callback,settings);
observer.observe(target);

//コールバック関数
function callback(a,b) {
  for(const value of a){
    if(value.isIntersecting === true){
      value.target.classList.add('is-inviewport')
    }else{
      value.target.classList.remove('is-inviewport')
    }

  }
}

Intersection Observerを使用するときのお作法

  1. 対象要素を監視する画面範囲、対象要素への変更を加えるタイミング、対象要素の監視間隔の設定オブジェクト
  2. IntersectionObserverコンスタクタでインスタンス化する。
    第一引数にコールバック関数、第二引数に1で設定した設定のオブジェクトを渡す。
  3. observeメソッドで監視開始

設定オブジェクトに関して

rootプロパティ
ターゲットが見えるかどうかを確認するためのビューポートとして使用される要素です。指定されなかった場合、または null の場合は既定でブラウザーのビューポートが使用されます。

rootMargin
root の周りのマージンです。 CSS の margin プロパティに似た値を指定することができます。例えば、”10px 20px 30px 40px" (top, right, bottom, left) のようなものです。この値はパーセント値にすることができます。この一連の値は、交差を計算する前にルート要素の範囲のボックスの各辺を拡大または縮小させることができます。既定値はすべてゼロです。

threshold
単一の数値または数値の配列で、ターゲットがどのくらいの割合で見えている場合にオブザーバーのコールバックを実行するかを示します。見える範囲が 50% を超えたときのみ検出する場合は値 0.5 を使用します。 25% を超える度にコールバックを実行する場合は、 [0, 0.25, 0.5, 0.75, 1] という配列を指定します。既定値は 0 です(つまり、 1 ピクセルでも表示されるとコールバックが実行されます)。 1.0 の値は全てのピクセルが見えるようになるまで、閾値を超えたとはみなされないことを意味します。

https://developer.mozilla.org/ja/docs/Web/API/Intersection_Observer_API の引用

コールバック関数に関して

コールバック関数の第一引数にはIntersectionObserveEntryオブジェクトが渡される。
isIntersectionプロパティやtargetプロパティがよく使われるプロパティらしい。
スクリーンショット 2023-02-11 22.47.16.png

第2引数にはIntersectionObserverオブジェクトが与えられる。中身を見ると、設定したrootMarginやthresholdsプロパティ、ここでは設定していないrootプロパティがnullで返されている。
スクリーンショット 2023-02-11 22.49.18.png

コード解説

設定オブジェクト

const settings = 
  rootMargin: '-50% 0px',
  threshold: [0],
}

rootMarginプロパティで-50% 0pxを指定。

rootプロパティを用意していないので、監視対象の反映は画面=ビューポートとなる。

rootMarginで-50%と指定しているため、対象要素の上辺がビューポートの半分を通過した時点で処理は始まり、対象要素の下辺がビューポートの半分を通過した時点で別の処理が走る。

thresholdプロパティで0を指定しているが、これはrootプロパティで指定した要素に対して交差している割合を示し、そのときにコールバック関数が発火する。

したがって、コールバック関数が発火するタイミングは

対象要素の上辺もしくは下辺が真ん中に差し掛かったとき。
スクロールの方向によって対象要素の上辺なのか下辺なのかが変わる。

コールバック関数

function callback(a,b) {
  for(const value of a){
    if(value.isIntersecting === true){
      value.target.classList.add('is-inviewport')
    }else{
      value.target.classList.remove('is-inviewport')
    }
  }
}

要素が設定した対象範囲に入ってきたかどうかの判定をしている。

入ってきたらis-inviewportクラスを付与して文字色を変えて、監視対象画面から外れたらクラスを外す定番の処理。

インスタンス化して監視対象を監視

const observer = new IntersectionObserver(callback,settings);
observer.observe(target);

まとめ

今回は、案件の背景上なるべく他プラグインを導入しないほうが良いとの判断でバニラJSで完結するIntersection Observerを実装してみた。

GSAPを使用したことがあれば、コールバック関数の引数に何が与えられるのか第二引数に渡す設定オブジェクトの内容 を知っていればあまり抵抗なく使えると思ったので、使い場所はあると思う。

サイトのパフォーマンスに大きな影響を与えることがなく、特殊プラグインの読み込みもないため尚良しだと思った。

参考文献

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?