Intersection Observer
参考サイト
//1.インスタンスの生成 コールバック関数の登録
const observer = new IntersectionObserver(func);
//2.監視要素を登録
observer.observe(document.querySelector('.mainvisual'));
//3. 1で登録するコールバック関数
// funcの第一引数にIntersectionObserverEntryオブジェクトの配列が渡る
function func(entries){
//entries.forEach(e=>{});
for(e of entries){
if(e.isIntersecting){
console.log(e.intersectionRatio);
e.target.classList.add('showTime');
}else{
console.log(e.intersectionRatio);
e.target.classList.remove('showTime');
}
}
}
// これで監視要素が領域(デフォルトではブラウザ)に入った時と出た時に
// 登録したコールバック関数が発火する。
// よって、発火の条件(optionで変更可)を満たしたときは
// intersectionRatio は true(入った時) か false(出た時) になります。
//2.監視要素を登録
//observer.observe(document.querySelector('.mainvisual'));
sections.forEach(section=>{
//1つ1つ登録する必要がある。
observer.observe(section);
});
// これはできない observer.observe(sections);
- 監視要素はメイン画像
- メイン画像が画面にあるかないかを判断して
- ない場合はheader要素にfixedクラスをaddする
- ある場合はheader要素のfixedクラスをremoveする
<div id="mainvisual">
<img src="https://source.unsplash.com/1600x900/?dogs" alt="">
</div>
<header class="">
<ul class="navi">
<li>LOGO</li>
</ul>
</header>
<main></main>
<script>
const header = document.querySelector('header');
//instanceの生成-関数を登録
const observer = new IntersectionObserver(toggleFixed);
//監視要素を登録
observer.observe(document.querySelector('#mainvisual'));
function toggleFixed(entries) {
entries.forEach(e => {
//実質処理はここから
if (e.isIntersecting) {
//default設定時は監視要素が
//画面にある時
header.classList.remove('fixed');
} else {
//ない時
header.classList.add('fixed');
}
});
}
</script>
See the Pen Untitled by y0sh1m0t0 (@y0sh1m0t0) on CodePen.
# 設定できるオプション//下はdefaultの設定
let options = {
root: null,//viewport
rootMargin: '0px',
threshold: 0
}
//instance時、第2引数に登録する
let observer = new IntersectionObserver(callback, options);
-
root
- defaultはviewport
- スクロールをもつ要素を指定することで対象を変更できる
-
root: document.querySelector('#main'),
-
-
rootMargin
See the Pen Untitled by y0sh1m0t0 (@y0sh1m0t0) on CodePen.
-
サンプル
-
画像の遅延読み込み
- rootMargin:'0px 0px 300px',
- 監視領域を下に300px拡大しているviewportに表示される前に画像を読み込んでいる
-
-
threshold: 0
- defaultは
0
で、この場合はintersectionRatio(交差量)
プロパティ(下に説明)の値を気にする必要がなく、監視要素がrootと交差した時に、isIntersecting
はtrue
になってcallback関数が実行される。また、交差が外れた時にisIntersecting
はfalse
になるので、この際にも、callback関数が実行される。 - 下のサンプルは、
threshold
がdefaultの0
の時、領域と交差した時にisIntersecting
はtrue
になりコールバック関数が実行され、交差が外れた時にisIntersecting
はfalse
になって再度コールバック関数が実行される動作を可視化してみました。
- defaultは
See the Pen Untitled by y0sh1m0t0 (@y0sh1m0t0) on CodePen.
-
上記で見た通り
threshold
が0
の時はisIntersecting
の判定は交差しているかどうかだけでしたが、50%ぐらい要素が交差した段階でコールバック関数を実行したい場合には、交差量を判定条件に入る必要があります。その際、threshold
の値を変更します。交差量が50%になった時にコールバック関数を実行したいときはthreshold
の値を0.5
に設定します。 -
intersectionRatio
プロパティとは- 交差量の値を取得することができるプロパティで以下の注意点があります。
- 監視要素を100%として 監視要素と監視領域との交差割合が
intersectionRatio
プロパティの値になる。 - 交差している値は0.0〜1.0で表示される。
- root領域が100%ではない。
-
オプションの
threshold
の値を変更することで、isIntersecting
のtrue
とfalse
の判定条件として交差量を付け加えることができる。 -
threshold: 1.0
だとisIntersecting
の判定は交差しておりかつ、intersectionRatio
が100%
の時にisIntersecting
はtrue
になってコールバック関数が実行される。intersectionRatio
が100%
未満になった時にisIntersecting
はfalse
になって再度コールバック関数が実行される。- よって1.0で下記の図の場合、コールバック関数は実行されない。
-
intersectionRatioとrootとの交差割合の関係を可視化してみたけど余計意
味が分からなくなったデモサイト
下のコードペンは私が書いたものではありません
- 下のコードペンは
- オプションの設定は
threshold: 0.5
で`rootmargineが0の画面全体が領域になってます。 - ということは
isIntersecting
がtrueになる条件は 交差 かつintersectionRatio(交差量)
が50%の時にtrueになり、コールバック関数が実行され、intersectionRatio(交差量)
が50%未満になった時にisIntersecting
はfalse
になってコールバック関数が再度実行されている動作を可視化したものになっています。
- オプションの設定は
See the Pen Trigger animations with IntersectionObserver API by Liquid Light (@liquidlight) on CodePen.
- 複数の threshold: [0.5,1.0]
-
threshold
は配列で 複数登録もできる。 - 上の場合intersectionRatioが50%,100%の条件を
満たした毎にコールバック関数が実行される。 - 上の場合、
isIntersecting
がfalse
になる条件はintersectionRatioが50%未満になった時でその際にもコールバック関数が実行される。- 100%の条件を満たした後,100%以下になった時(100%以上はありえない)に、isIntersectingは'true'のままでコールバック関数は実行されません。再度100%になった時にはコールバック関数は実行され、50%以下になった時に isIntersectingは
false
になってコールバック関数が実行されます。
- 100%の条件を満たした後,100%以下になった時(100%以上はありえない)に、isIntersectingは'true'のままでコールバック関数は実行されません。再度100%になった時にはコールバック関数は実行され、50%以下になった時に isIntersectingは
-
threshold作成の公式
let options = { root: null, rootMargin: "0px", threshold: buildThresholdList() }; function buildThresholdList() { let thresholds = []; //numStepsを変更することで必要な数を追加できる。 //監視要素を100分割したかったら100 let numSteps = 20; for (let i = 1.0; i <= numSteps; i++) { let ratio = i / numSteps; thresholds.push(ratio); } thresholds.push(0); return thresholds; }
-
- 用途としては、要素の中をスクロールイベントのようにスクロール量に応じて変化させたい時に相応に分割して要素内でスクロールの上下に応じてイベントを発生させることができます。
下のコードペンは私が書いたものではありません
- 下のコードペンでは監視要素を1/200分割して監視領域での交差量をコールバック関数で取得してその値でtextContent(data)を書き換えています。
-
See the Pen Intersection Observer API Demo by Ion Drimba Filho (@iondrimba) on CodePen.
その他
See the Pen Untitled by y0sh1m0t0 (@y0sh1m0t0) on CodePen.
-
その他
-
unobserve
- 登録要素の監視を終了させる。
-
observer.unobserve(entry.target);
-
disconnect
- オブザーバーに変更の監視を停止させます。
- オプションやコールバック関数を変更したい時に
一旦停止して再度登録すると初期化できる。 - 停止させずに登録すると前の
コールバック関数とオプションも残った状態になる。 -
observer.disconnect();
-
'IntersectionObserver' in window
- IntersectionObserverが使用可能かどうか
判定してくる。 -
if ('IntersectionObserver' in window) { //処理 }
- IntersectionObserverが使用可能かどうか
-
IE11への対策
-
IE11はIntersection Observerに対応していませんが、以下のpolyfillを1行読み込ませるだけで対応可能になります。
-
<script src="https://polyfill.io/v3/polyfill.min.js?features=IntersectionObserver"></script>
-
無限スクロール
See the Pen Untitled by y0sh1m0t0 (@y0sh1m0t0) on CodePen.