ある要素が画面内にあるか否かで web ページの動作を変えることがままあります。これを実現するのによく使われるのが画面と要素の位置と大きさを測る関数をスクロールイベントで発火させる方法です。画面と要素の位置と大きさを画面が移動する度に測るので、ある要素が画面内に入ってきた、出て行ったを逃すことなく捉えられます。この方法は確かに動くのですがブラウザ、コンピュータに負荷を強いやすいという問題点があります。次の動画が例で、ちょっとしたスクロールでも10回、20回とイベントが連続で発火していることがわかります。このため、スクロールイベント内の1度の処理の負荷が重くなるとその負荷は10倍、20倍となってブラウザにかかります。
こういった高負荷処理は避けるべきです。ある要素の出入りを待ち受けたいのであれば Intersection Observer API を使うことで低負荷な処理を実現できます。
Intersection Observer API – Web API | MDN
Intersection Observer API はある要素と要素が交わることを監視するための機能です。これは画面と要素の交わる、交わらないのタイミングも監視してくれます。デモが次です。デモ画面中の下の方にある赤四角の画面内への出入りを監視しています。
ソースコード
if(window.IntersectionObserver){// IntersectionObserver が未実装のブラウザ用のガード let i = 0; const observer = new IntersectionObserver((entries) => { // entriesは監視対象すべてが入っているリストです // @see https://developer.mozilla.org/ja/docs/Web/API/IntersectionObserverEntry for(const e of entries) { // isIntersecting プロパティに内、外の情報が入っています i++; if(e.isIntersecting){ document.getElementById('msg').innerText = i + '回発火 現在:IN'; }else{ document.getElementById('msg').innerText = i + '回発火 現在:OUT'; } } }); // オブザーバインスタンスのobserve メソッドに監視対象要素を引数として渡すことで監視がされるようになります observer.observe( document.getElementById('tgt') ) }
イベントの発火回数が最小限で済みます。このため、発火時の処理内容が重くともスクロールイベントを用いた方法よりも格段に快適にブラウザを使ってもらえます。