MobileSafari でプログレスバーを出さないように画像を読み込む

MobileSafari では、どうやら window load のタイミングで画像の読み込みを開始したとしても、その画像の読み込みが完了するまでプログレスバーが表示され続けます。setTimeout などで読み込み開始時間をずらせば回避できますが、プログレスバーが消えたタイミングを取得する術はありません。
何が困るって、バックグラウンドで画像を読み込みたいのに、プログレスバーの表示が終わる前に読み込みを開始するとめちゃくちゃ重いページみたいな印象を与えてしまうわけです。

どうやら、XHR であれば通信中であってもプログレスバーが消えるようなので、次のサンプルコードの loadImage のようにして画像を取得すれば良さそうです。

<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=320,user-scalable=no">
</head>
<body style="width:100%; height:1000px;">
<img id="img" width="100" height="75">
<script>
function loadImage(img, url, callback) {
  if (location.search.indexOf('lazy=1') !== -1 && window.URL) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', url);
    xhr.responseType = 'blob';

    xhr.addEventListener('load', function(evt) {
      if (this.status === 200) {
        var blob = this.response;

        img.addEventListener('load', function(evt) {
          window.URL.revokeObjectURL(img.src);
          if (callback) {
            callback(evt);
          }
        });
        img.src = window.URL.createObjectURL(blob);
      }
    });

    xhr.send();
  } else {
    if (callback) {
      img.addEventListener('load', callback);
    }
    img.src = url;
  }
}

var imageUrl = 'http://dev.abicky.net/hatena/pack_image/wood-fence-texture-04.png?s=' + Date.now();

window.addEventListener('load', function(evt) {
  loadImage(document.getElementById('img'), imageUrl);
});
</script>
</body>
</html>

注意点

  • blob がサポートされてないとけっこう辛い処理が必要
  • 画像のドメインが異なる場合はヘッダに Access-Control-Allow-Origin を付与する必要がある

大きめの画像を読み込む時に試してみると、体感速くなったように感じてもらえるかもしれないですね!