2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Intersection Observer メモ

Last updated at Posted at 2022-03-30

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);

image.png

サンプル
image.png

  • 監視要素はメイン画像
  • メイン画像が画面にあるかないかを判断して
  • ない場合は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

    • defaultはroot全体の'0% 0% 0% 0%';
    • 単位は0でも必須 %とpx が使える
    • 正の値だとrootの外側に拡大する
    • 負の値だとrootの内側に縮小する
    • 下の画像はrootMargin:'-10% 0% -10% 0%',の時を可視化したもの
      • image.png
    • rootMargin:'-50% 0%',の時は領域は線になる
      • image.png
      • 下のコードペンは負の時のルートマージンの領域を可視化してみた

See the Pen Untitled by y0sh1m0t0 (@y0sh1m0t0) on CodePen.

  • サンプル

  • 画像の遅延読み込み

    • rootMargin:'0px 0px 300px',
    • 監視領域を下に300px拡大しているviewportに表示される前に画像を読み込んでいる
  • threshold: 0

    • defaultは 0で、この場合はintersectionRatio(交差量)プロパティ(下に説明)の値を気にする必要がなく、監視要素がrootと交差した時に、isIntersectingtrueになってcallback関数が実行される。また、交差が外れた時にisIntersectingfalseになるので、この際にも、callback関数が実行される。
    • 下のサンプルは、thresholdがdefaultの0の時、領域と交差した時にisIntersectingtrueになりコールバック関数が実行され、交差が外れた時にisIntersectingfalseになって再度コールバック関数が実行される動作を可視化してみました。

See the Pen Untitled by y0sh1m0t0 (@y0sh1m0t0) on CodePen.

  • 上記で見た通りthreshold0の時はisIntersectingの判定は交差しているかどうかだけでしたが、50%ぐらい要素が交差した段階でコールバック関数を実行したい場合には、交差量を判定条件に入る必要があります。その際、thresholdの値を変更します。交差量が50%になった時にコールバック関数を実行したいときはthresholdの値を0.5に設定します。

  • intersectionRatioプロパティとは

    • 交差量の値を取得することができるプロパティで以下の注意点があります。
    • 監視要素を100%として 監視要素と監視領域との交差割合がintersectionRatioプロパティの値になる。
    • 交差している値は0.0〜1.0で表示される。
    • root領域が100%ではない。
  • image.png

  • オプションのthresholdの値を変更することで、isIntersectingtruefalseの判定条件として交差量を付け加えることができる。

  • threshold: 1.0だとisIntersectingの判定は交差しておりかつ、intersectionRatio100%の時にisIntersectingtrueになってコールバック関数が実行される。intersectionRatio100%未満になった時にisIntersectingfalseになって再度コールバック関数が実行される。

下のコードペンは私が書いたものではありません

  • 下のコードペンは
    • オプションの設定はthreshold: 0.5で`rootmargineが0の画面全体が領域になってます。
    • ということはisIntersectingがtrueになる条件は 交差 かつ intersectionRatio(交差量)が50%の時にtrueになり、コールバック関数が実行され、intersectionRatio(交差量)が50%未満になった時にisIntersectingfalseになってコールバック関数が再度実行されている動作を可視化したものになっています。

See the Pen Trigger animations with IntersectionObserver API by Liquid Light (@liquidlight) on CodePen.

  • 複数の threshold: [0.5,1.0]
    • thresholdは配列で 複数登録もできる。
    • 上の場合intersectionRatioが50%,100%の条件を
      満たした毎にコールバック関数が実行される。
    • 上の場合、isIntersectingfalseになる条件はintersectionRatioが50%未満になった時でその際にもコールバック関数が実行される。
      • 100%の条件を満たした後,100%以下になった時(100%以上はありえない)に、isIntersectingは'true'のままでコールバック関数は実行されません。再度100%になった時にはコールバック関数は実行され、50%以下になった時に isIntersectingはfalseになってコールバック関数が実行されます。
    • 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) { 
                 //処理
           }
      
  • 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.

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?