menu
書いてる野郎
orebike@gmail.com
【注意】ここにある情報は筆者の理解が浅い、もしくは検証環境がおかしいため嘘の情報が含まれている可能性が高いです。参考にしないでください。
ブラウザの可視範囲に入ったら何かするやつ jQuery を使わなくても簡単にできる。
var options = { root: document.querySelector('#piyo'), rootMargin: "10px", threshold: 1.0 } var observer = new IntersectionObserver(function(entries, observer) { entries.forEach(entry => { if(entry.isIntersecting){ console.log("hogehoge"); } }); }, options); var targetList = document.querySelectorAll("#piyo .hoge"); for(let target of targetList){ observer.observe(target); }
これがオプション
var options = { root: document.querySelector('#hoge'), rootMargin: 0, threshold: 1.0 }
root
は監視対象を内包するオブジェクトを指す。
このオブジェクトのサイズが表示されたとみなす範囲になる。
指定なしは画面全体(つまり普通に画面で見えている範囲全体)を指す。
これは単一の DOM である必要がある、(querySelectorAllで取得するような)複数の要素を一気に指定することはできない。
ではどのような場合にこの指定するかというと、
#hoge{ height: 100px; over-flow: auto; }
のように要素の中身の表示が意図的に限定されている場合に設定する。つまり疑似フレームみたいな状況。
この場合は高さは 100px
で限定されているので内容物が 100px
以上ある場合その部分が切れて表示される。
auto
に指定してあるので、その部分はスクロールバーが出てスクロール可能状態になっている。
そのスクロールでスクロールさせて、その切れて見えなくなってる部分が表示されたら発火する。
root
を実際の範囲よりどの程度デカくみなすか。
デカくみなすとは実際に表示されるよりも手前でイベントが発火する。 画像の先行ロード等で表示してからでは間に合わないみたいな場合に若干大きめの値を設定する。
デフォルトは 数値0
、px
や %
でも指定できる。その場合は文字列で指定する。
対象の要素がどの程度見える状態になるとイベントが発火するかを設定する。
1
は対象が内に完全に入った場合に発火、0.5
なら半分、0
だと入る直前に発火する。
名前の通り「監視者」を作る。
var observer = new IntersectionObserver(function(entries, observer) { entries.forEach(entry => { if(entry.isIntersecting){ console.log("hogehoge"); } }); }, options);
第一引数にコールバック関数を取る。このコールバックは内部の監視対象が表示の条件に合致したら呼び出される。 どの監視対象が合致しても呼び出される。
このコールバック関数は大きく3つのタイミングで呼び出される。
observe
メソッドで何かが登録されてそれを監視開始する直後observe
メソッドは複数回連続で呼ばれることが普通で、連続で呼び出すとその塊が1個として発火するobserve
を登録するとそのタイミングでも発火するこいつは表示しているしていないではなく交差を見ているのでこのようなタイミングで発火する 交差を見ているのでそいつが画面上にモノとして見えているかどうかは関係ない
コールバックの第1引数には監視対象を付加情報でラップしたモノが渡される。 この監視対象はタイミングによってちょっと渡されるモノが変化するので注意する必要がある。
まず↑に示した登録して一発目の監視開始時は無条件で全登録対象が entries
に入ってくる。
しかしタイミングをズラした場合はそのズラした監視対象だけ入ってくる。
observe
したタイミングで無条件で対象に対して1回実行されるとおぼえておけば良い。
そして次からは監視対象でそれが交差した対象が入ってくる。 状況によってはここに2つ同時に入ってくる可能性もある。
普通に監視対象に対してイベントが発火するタイミングは(最初の登録時を除いて)2回ある。 対象が条件を満たす瞬間と、条件から外れる瞬間である。
0.8
指定してた場合ならば、スクロールして 80% 入った瞬間に発火し、次に 100%
になりさらにスクロールして、画面から外れて 80%
になる瞬間に発生する。
ここで要素の画面割合が上昇側で入ったのか減少側で入ったのかを測る必要がある。
これが intersectionRatio
でイベントが発火したタイミングでの対象の画面要素表示割合を示してくれる。
仕様には明示されてないが、表示割合が上昇するタイミングでは threshold
よりも若干大きな値になり、画面割合が下降するタイミングでは threshold
よりも若干小さな値になるようだ。
これを基準に2回発火するイベントを使い分けることができるだろう。
殆どの場合において上昇側(画面に対象のある範囲が表示され続けるタイミング)で何かやりたいことがほとんどだと思うので threshold < intersectionRatio
のタイミングで何かやればいいだろう。
これは単に監視者。
observe メソッドで監視対象を監視者へ登録する。
var targetList = document.querySelectorAll("#piyo .hoge"); for(let target of targetList){ observer.observe(target); }
監視対象を特録するのが、これがいつのタイミングで開始されるのかがまったくわからない。 監視を停止するメソッドはあるが、逆に復帰するメソッドは無い。 監視対象を登録したタイミングでは無いようだ。
height: 100vh
のような状態で threshold: 1.0
指定してそのような要素が連続していると、
スクロールの最小単位の関係でピッタリ入った瞬間に出ていくという動作になることが多く、思った瞬間が捉えられないことがある。
なので threshold: 0.8
のように気持ち小さい値を入れておくとよい。