Javascript

読み込み速度に合わせて、表示させる画像を切り替える方法

読み込み速度に合わせてコンテンツや画像の表示を切り替える備忘録です。 動画サイトとかYoutubeで低速モードで、粗めの動画にして、動画が止まらないような仕組みがありますよね。イメージとしては同じです。

ページの読み込み速度は回線の速度だったり、ブラウザの表示速度だったり、様々な要因で速度が変わってきますよね。今回は、その読み込み速度に合わせて、表示させる画像を「等倍画像」と「2倍寸画像」の画像を切り替えてみます。

実際は「等倍画像」と「2倍寸画像」の切り替えは端末の解像度で切り替えるべきだと思います。今回の紹介記事では、読み込み速度に合わせて、表示させるコンテンツを切り替えれる参考と思っていただければ幸いです。

読み込み速度に合わせて画像を切り替えるデモ

まずは実際に作成したデモページのご紹介です。

ファイルの読み込み速度を「Mbps」単位で表示させて、今回は「5Mbps」以下の場合は「等倍画像」を表示させるように分岐させています。

全体コード

まずはデモの全体コードをです。

Javascript

$(function() {
    var loadImage = function(elem, speed) {
      if (!elem)
        return;
      if (speed == 'fast') {
        var src = elem.getAttribute('data-fast-src');
      } else if (speed == 'slow') {
        var src = elem.getAttribute('data-slow-src');
      }
      if (!src)
        return elem;
      var imgElem = document.createElement('img');
      elem.removeAttribute('data-fast-src');
      elem.removeAttribute('data-slow-src');
      imgElem.onload = function() {
        elem.setAttribute('src', src);
      };
      imgElem.setAttribute('src', src);
      return elem;
    };
    var speedCheck = function() {
      var SPEED_FLAG = 5.0;
      var IMAGE_BYTES = 102117;
      var IMAGE_BITS = IMAGE_BYTES * 8;
      var startTime = (new Date()).getTime();
      $.get('img/file_example_JPG_100kB.jpg?' + startTime, function(data) {
        var endTime = (new Date()).getTime();
        var diffSeconds = (endTime - startTime) / 1000;
        var mbps = parseFloat((IMAGE_BITS / diffSeconds / (1024 * 1024)).toFixed(2));
        $('.js-speed-text').text(mbps);
        if (mbps < SPEED_FLAG) {
          $('.js-branch-img').each(function(index, element) {
            $('.js-speed-text').css('color', 'red');
            loadImage(element, 'slow');
          });
        } else {
          $('.js-branch-img').each(function(index, element) {
            $('.js-speed-text').css('color', 'green');
            loadImage(element, 'fast');
          });
        }
      });
    };
    speedCheck();
  });

HTML

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>読み込み速度で画像サイズを分岐させる</title>
    <meta name="keywords" content="">
    <meta name="description" content="">
    <link rel="stylesheet" href="./css/common.css">
    <link rel="stylesheet" href="./css/style.css">
    <link rel="preconnect" href="<https://fonts.googleapis.com>">
    <link rel="preconnect" href="<https://fonts.gstatic.com>" crossorigin>
    <link href="<https://fonts.googleapis.com/css2?family=Oswald&display=swap>" rel="stylesheet">
    <script src="./js/jquery-3.6.0.min.js" defer></script>
    <script src="./js/main.js" defer></script>
  </head>
<body>
  <div id="contents-wrapper">
    <main>
      <section class="sec">
        <div class="sec__inner">
          <div class="flexItem">
            <div class="speedText">
              読み込み速度: <span class="number js-speed-text"></span> Mbps
            </div>
            <div class="note">
              読み込み速度が「5Mbps」以上の場合、メインの画像が「2倍寸画像」で読み込まれます。<br>
              読み込み速度が「5Mbps」以下の場合、メインの画像が「等倍画像」で読み込まれます。
            </div>
            <div class="infoFlexWrap">
              <div class="item">
                <div class="imgbox"><img src="./img/img_fast.png" alt=""></div>
                <p>読み込み速度が「5Mbps」以上</p>
              </div>
              <div class="item">
                <div class="imgbox"><img src="./img/img_slow.png" alt=""></div>
                <p>読み込み速度が「5Mbps」以下</p>
              </div>
            </div>
            <div class="note info">
              読み込み速度の調整は、<br>Chrome→検証モード→Network→No throttling→Fast 3G 等に変更可能です。
            </div>
          </div>
          <div class="flexItem">
            <div class="branchImg">
              <img class="js-branch-img" data-fast-src="./img/img01@2x.jpg" data-slow-src="./img/img01.jpg" alt="">
            </div>
          </div>
        </div>
      </section>
    </main>
  </div>
</body>
</html>

1.読み込み速度の計測方法について

読み込み速度の計測方法から説明していきます。 読み込み速度の計測については、以下のページを参考にさせていただきました。

https://blog.capilano-fw.com/?p=4928
// 読み込み速度の計測
var speedTest = function() {
  var SPEED_FLAG = 5.0; 
  var IMAGE_BYTES = 102117; 
  var IMAGE_BITS = IMAGE_BYTES * 8; 
  var startTime = (new Date()).getTime(); 
  $.get('img/file_example_JPG_100kB.jpg?' + startTime, function(data) {
    var endTime = (new Date()).getTime();
    var diffSeconds = (endTime - startTime) / 1000;
    var mbps = parseFloat((IMAGE_BITS / diffSeconds / (1024 * 1024)).toFixed(2));
    $('.js-speed-text').text(mbps);
    if (mbps < SPEED_FLAG) {
      $('.js-branch-img').each(function(index, element) {
        $('.js-speed-text').css('color', 'red');
        loadImage(element, 'slow');
      });
    } else {
      $('.js-branch-img').each(function(index, element) {
        $('.js-speed-text').css('color', 'green');
        loadImage(element, 'fast');
      });
    }
  });
};

  var SPEED_FLAG = 5.0; //5.0Mbpsで画像を分岐させる
  var IMAGE_BYTES = 102117; //測定用画像のサイズを指定
  var IMAGE_BITS = IMAGE_BYTES * 8; //1バイト=8ビット

画像を分岐させる速度を決める

定数「SPEED_FLAG」で画像を分岐させる読み込み速度を設定します。 Webページの読み込み速度の目安は以下を参考にしました。

今回は5.0Mbpsとしました。 Webサイトの閲覧:下り1Mbps〜10Mbps https://shibarinashi-wifi.jp/media/8574/

測定用画像のサイズを指定する

測定用画像は以下のサイトからダウンロードしていますが、実際はサイト内の必ず読み込む画像を指定するのがいいと思います。

画像サイズは画像情報から確認。 今回のサンプル画像のサイズは「102117」で大体102KBですね。 Chromeからは 検証モード→Network→画像をクリック→content-lengthで確認できます。 (macの場合、画像ファイルを右クリックで、情報を見る→サイズ確認でも同じです)

バイト単位をビット単位に変換する

画像のファイルサイズ「バイト単位」を回線速度計測の「ビット単位」に変換しておきます。 回線速度やファイルサイズの単位については、以下のページが参考になりました。

https://note.cman.jp/network/bpsbs/

画像の読み込み速度の計測スタート

var startTime = (new Date()).getTime(); //読み込み開始時間
	// 測定用画像はキャッシュしないように、読み込み開始時間をパラメータに付与
  $.get('img/file_example_JPG_100kB.jpg?' + startTime, function(data) {
    var endTime = (new Date()).getTime(); //読み込み終了時間
    var diffSeconds = (endTime - startTime) / 1000; //読み込み時間
    var mbps = parseFloat((IMAGE_BITS / diffSeconds / (1024 * 1024)).toFixed(2)); //1K=1024でMbps値に変換させる
    $('.js-speed-text').text(mbps);
  });

「startTime」で読み込み開始時間を取得します。

測定用画像はキャッシュしないように、読み込み開始時間をパラメータに付与

測定用画像にキャッシュが残ると、1回目の読み込みと、2回目の読み込みで読み込み速度が変わってしまうので、キャッシュさせないように、読み込み開始時間をパラメータとして付与しておきます。

Mbpsに変換する

測定した時間からmbps単位で速度を出します。

var mbps = parseFloat((IMAGE_BITS / diffSeconds / (1024 * 1024)).toFixed(2));

5.0Mbpsで処理を分岐させる

「SPPED_FLAG」に指定した速度で処理を分岐させます。

    if (mbps < SPEED_FLAG) {
      $('.js-branch-img').each(function(index, element) {
        $('.js-speed-text').css('color', 'red');
        loadImage(element, 'slow');
      });
    } else {
      $('.js-branch-img').each(function(index, element) {
        $('.js-speed-text').css('color', 'green');
        loadImage(element, 'fast');
      });
    }

2.画像を読み込む処理

画像を読み込む処理を用意します。画像の読み込みについては、以下サイトを参考にさせていただきました。

https://shanabrian.com/web/javascript/load-images-later.php

HTMLの「img」タグにsrcは記載せずに、回線早い時用のsrc「data-fast-src」回線遅い時用のsrc「data-slow-src」を用意します。srcタグがあると、JSで速度判別前に結局読み込まれてしまってりします。

<img class="js-branch-img" data-fast-src="./img/img01@2x.jpg" data-slow-src="./img/img01.jpg" alt="">

    var loadImage = function(elem, speed) {
      if (!elem)
        return;
      if (speed == 'fast') {
        var src = elem.getAttribute('data-fast-src');
      } else if (speed == 'slow') {
        var src = elem.getAttribute('data-slow-src');
      }
      if (!src)
        return elem;
      var imgElem = document.createElement('img');
      elem.removeAttribute('data-fast-src');
      elem.removeAttribute('data-slow-src');
      imgElem.onload = function() {
        elem.setAttribute('src', src);
      };
      imgElem.setAttribute('src', src);
      return elem;
    };

回線が早いの時は「data-fast-src」を遅い時は「data-slow-src」をimgの「src」として読み込みます。

あとは、分岐に合わせて関数を指定すればOKです。

if (mbps < SPEED_FLAG) {
      $('.js-branch-img').each(function(index, element) {
        $('.js-speed-text').css('color', 'red');
        loadImage(element, 'slow');
      });
    } else {
      $('.js-branch-img').each(function(index, element) {
        $('.js-speed-text').css('color', 'green');
        loadImage(element, 'fast');
      });
    }

完成したデモがこちら

最後に

今回は読み込み速度に合わせてコンテンツや画像を切り替える方法をご紹介いたしました。

動画や重たいコンテンツを表示させたい時に、読み込み速度で分岐させるとユーザビリティがアップしそうですね。

プログラミング言語の人気オンラインコース