どうも、Morimotoです。
この記事では、「IntersectionObserver」を使ったスクロールアニメーションについて解説します。
スクロールアニメーションは↓みたいなやつ
これまではjQueryのスクロールイベントを使ってスクロールアニメーションを実装してきましたが、最近塚本氏に「IntersectionObserver」なるものを教えてもらったので、勉強もかねて現在コーディング中のサイトで実装しています。
実装にあたって疑問点も多く、つまづいたりしたので備忘録もかねて実装方法を記事に残したいと思います。
IntersectionObserverとは
最初教えてもらったときに、「IntersectionObserverって何?」となったので、まず意味を調べてみることに。
それぞれの単語を辞書で引くと
- intersection:交切、交差、横断、交点、交線
- observer:観察者、観測者、監視者
という意味があるので、「IntersectionObserver = 要素が交差するのを監視するやつ」となります。
そこから使い方などを調べていくと、基本的にはスクロールをしていって「ビューポート(見ている画面)」と「アニメーションする要素」が交差した(画面内に入った)ときに関数を実行させられるということが分かりました。
ここまで知ると、「jQueryのscrollイベントの方法と変わらないじゃん。別にscrollイベントでも良くない?」となるかもしれません。
スクロールアニメーションにIntersectionObserverの使用をオススメする理由
実装することが変わらなくて、jQueryに慣れているならこれからもscrollイベントを使ったスクロールアニメーションを使いたくなりますよね。
しかし、これからはIntersectionObserverを使ってほしいと思います。
なぜなら、IntersectionObserverの方が負荷が小さいからです。
英語のサイトですが、下記サイトを見てください。
Scroll listener vs Intersection Observers: a performance comparison
IntersectionObserverとscrollイベントのパフォーマンスの違いをまとめたサイトになります。
IntersectionObserverの方が約2倍もパフォーマンスが良いことが分かります。
1pxごとに処理が実行されるscrollイベントと違い、IntersectionObserverは交差したタイミングで関数が呼び出されるので、圧倒的に負荷が小さいんですね。
なので、スクロールアニメーションの実装にはIntersectionObserverの使用をオススメします。
IntersectionObserverを使ったサンプルコード
ここまでIntersectionObserverの概要について書いてきましたが、ここからは簡単なアニメーションを使ったコードを紹介します。
サンプルとして背景色が変わるアニメーションを作りました。
交差したらアニメーション用のクラスを付けてbackground-colorを変えるような仕様となっています。(アニメーションは1回のみの設定)
コードは下記の通りです。 https://codepen.io/pmegrldp-the-bashful/embed/qBLGQmZ?default-tab=result
アニメーションの発火位置設定を変える
optionsの「root」「rootMargin」「threshold」を変えることで、発火位置などを変えることができます。
root
rootは、どの要素を基準にするかを決定できます。
デフォルトはnullで、ビューポート(画面の大きさ)が基準になります。
ちなみにここで紹介しているサンプルコードはCODEPENを使っていて、CODEPEN上で動作するようにrootにposition:fixed;で固定した画面全体を囲むdiv要素を指定していますが、基本的にはnullで大丈夫です。
rootMargin
rootMarginは設定したrootからの交差位置を設定できます。
たとえばrootMargin:‘20% 0px’,
とすると、rootの基準から上下位置が20%広がった位置で交差判定されます。
CSSのmarginプロパティのように’20px 0px 40px 0px’といった感じで上下左右の設定もできます。
0の場合も単位が必要となるので注意しましょう。
ビューポートが基準となった状態で、rootMarginの値をマイナスにすると画面内にどれくらい入ったかで交差判定がされるので、場合によって使い分けましょう。
threshold
thresholdは0~1の値を設定でき、「ターゲットの要素がどれくらい基準の要素と交差したか」を決めることができます。
0にすれば交差した瞬間で、1にすれば要素全体が交差し終わったときにアニメーションが発火されます。
「要素が〇%見えたら発火させたい」といった場面で使えます。
ちょっとだけカスタマイズしてみる
基本的な使い方は上記の通りですが、少しだけカスタマイズしてみます。
ターゲットが複数ある場合
サンプルコードのようにアニメーションさせたい要素が1つではなく、同一ページ内に複数あった場合は下のようになります。(アニメーションは1回のみの設定)
クラスをquerySelectorAllで取得し、forEachで監視と実行する関数をループするようになります。
往復スクロールでそれぞれ発動させたい場合
下にスクロールしてアニメーションが発火されると背景色は赤色のままですが、上にスクロールするときもアニメーションを発火させたいときは下のようになります。
実行する関数のif文が「要素が交差したら」の判定なので、elseで交差していない状態のときにクラスを取り除くようにします。
そうすることで、交差し終わったときに要素がアニメーション前の状態に戻ります。
ちなみに、上のサンプルような上下どちらでも発火するアニメーションではなく、下にスクロールしたときに1回だけ発火して終わり、といったような場面ではIntersectionObserverの監視を止めてあげるとパフォーマンスがちょっと良くなります。
なので、アニメーションを1回発火させたら終わる場合、以降の監視を止めるために下記の1行を追記しておきましょう。
observer.unobserve(entry.target);
これで要素が交差する(アニメーションが終わる)と監視も止まるようになります。
アニメーションが動作しないときのチェックポイント
ここまでIntesectionObserverの基本的な使い方を紹介しました。
実装したいアニメーションに合わせてカスタマイズしていただければと思いますが、ちゃんと動かないときはサンプルコードを見ながら下記の項目をチェックしてみてください。
- rootMarginが0のときでも単位(「px」「%」)が必要
- 関数の呼び出し忘れ
- アニメーション設定(CSS)のミス
- スペルミス
まとめ
jQueryによるスクロールアニメーションは、手軽にサイトに動きを加えることが出来るのでよく使われると思いますが、多用しすぎるとサイトパフォーマンス低下につながってしまいます。
少しでもサイトパフォーマンスを上げるためにも、これからはIntersectionObserveを使っていこうと思います。
最初は使い方が分からず調べながらの実装になると思いますが、1回やれば次からはすんなり出来ると思うので、まだ使ったことが無い方はぜひ使ってみてください。
それでは。