広告
Javascriptで画像の遅延読み込み(ライブラリなしで)

画像が多いページ、読み込みが遅くて困ることがありませんか?
私のサイトのイラストはまさしく画像が多くて遅くなっていました。
そこで画像が本当に必要になるまで読み込みを行わない遅延読み込みを実装しました。

遅延読み込みを使うことで のようにしてページの表示速度を改善することができます。

実装の上では というような方針を取ります。
以下は実際のコードです。
<html><body>
  <table id="table"> <!-- このテーブルにjsからデータを入れる -->
  </table>

  <script>
    var table = document.getElementById("table");
    table.style.tableLayout = "fixed";
    var data = [
      [
        "ayame5.html",
        "./img/20200307_3_thumbnail.png",
        "関あやめ(☆5)",
      ],
      // ---表示用データのため中略 ---
    ];

    var ncols = 5;
    current_item_num = 0;

    // 画像をテーブルに追加
    function addItem()
    {
      if(current_item_num >= data.length)
        return;
      if(current_item_num % ncols == 0){
        row = table.insertRow( -1 );
        var th = document.createElement( 'th' );
        row.appendChild( th );
      }

      // テーブルにセルを追加
      var td = row.insertCell( -1 );
      td.pixelWidth = 120;
      td.width = "120px";
      td.height = "160px";
      td.style.verticalAlign = "top"

      // 画像を設定
      var thumb = document.createElement("a");
      v = data[current_item_num];
      thumb.href = v[0];
      var img = document.createElement("img");
      img.src = v[1];
      img.width = 100;
      img.height = 100;

      // 画像の周りのテキストなどを設定
      thumb.appendChild(img);
      td.appendChild(thumb);
      td.appendChild(document.createElement("br"));
      var link = document.createElement("a");
      link.href = v[0];
      var txt = document.createElement("div");
      txt.innerHTML = v[2];
      txt.style.overflow = "hidden";
      link.appendChild(txt);
      td.appendChild(link);
      current_item_num++;
    }

    // スクロールした分が埋まるまでaddItemを呼ぶ
    function addItemsToFillHeight()
    {
        cr = table.getBoundingClientRect();
        if(window.innerHeight + 100
          <= cr.bottom)
          return;
        for(i = 0; i < ncols; i++)
          addItem();
        setTimeout(addItemsToFillHeight, 10);
    }

    // スクロールを検知
    window.addEventListener('scroll', (e) =>
    {
        addItemsToFillHeight();
    });

    // ページ読み込み時にも初期表示用に一度だけデータを入れておく
    addItemsToFillHeight();

  </script>
</body></html>


テーブルに十分にアイテムが入ったかどうかの判定はテーブルのバウンディングボックス (テーブルが表示されている領域を座標で表したもの)とウィンドウが表示している領域を 比較することで行います。
コードでは実際に
table.getBoundingClientRect().bottom: テーブルの下部のy座標
window.innerHeight: ウィンドウがスクロール込みでページの高さのどこまでを表示しているか
の比較をl.65で行っています。

動いている様子はここで確認できます。
読み込んだ直後は下図のように5行しかテーブルに入っていませんが (注:行数はディスプレイのサイズに依存します)


スクロールしていくと下図のようにテーブルの行数が増えていることが見て取れます。