Infinity loadingなどで使う、ページを90%まで読み込んだ時に処理を実行する方法について、Intersection Observerを使って実現が意外に難しかった。
あまり自信ないやり方なので、もっといいやり方あったら教えて欲しいです。
従来のやり方
document.addEventListener('scroll', function() {
const scrollRate = window.pageYOffset / (document.documentElement.scrollHeight + document.documentElement.clientHeight);
if (scrollRate > 90) {
/* 何らかの処理 */
}
});
このようにscrollイベントを監視して、scrollが行われるたびに現在のスクロール率を再計算する方法です。
このやり方だと、scrollするたびに判定処理が走るため、ページの動きが重くなりやすいです。
Intersection Obverver
scrollの課題を解決するために、最近のブラウザだと Intersection Ovserver
が定義されているのですが、これで元々やりたかったページ全体の90%スクロールしたら表示するという方法が意外と難しかった。
Intersection Observerは名前が示す通り、交差する要素を指定するために、以下の3つの要素を指定します。
const observer = new IntersectionObserver(() => {
/* 何らかの処理 */
}, {
root: null,
rootMargin: "0px",
threshold: 0.9,
});
const target = document.querySelector('body');
observer.observe(target);
- root & rootMargin
- 監視をする視点側
- target
- 監視される対象
- threshold
- 交差度合い
bodyを指定した場合、viewportのデフォルトである画面上には、常にbody全体が指定されるため、この場合の 交差率
は常に一定になって、0.9には届きません。
スクロール率90%を実現する
結論から言うと、以下のようにviewportをずらすことで解決できます。
root: null,
rootMargin: "-100% 0px 100% 0px",
threshold: 1.0 - 0.9,
このように設定すると、ブラウザの表示領域の下の領域にまだどれくらいの要素が残っているかが計測できるため、残りが 0.1 = 0.9スクロールしている、ということが計算できます。
bodyの大きさによっては、viewportをの大きさを変えたりなど、更なる調整をしないとうまく動かないケースもあるかもしれないです。
Intersection Observerでスクロール率を計算する方法
viewportをブラウザの表示領域の下部にずらすことで実現できました。
ただ、あまり直感的な使い方ではなく、フッターなどをtargetに指定したほうが素直ですので、できるならその通り実装することをお勧めします。