画像の先読み

実現のためのコードはいたってシンプルです。以下のようにします。

var imgObj = new Image();
imgObj.src = "sample1.jpg";

JavaScriptでImageオブジェクトのsrcプロパティに画像アドレスを設定すると、その時点でブラウザが画像をダウンロードするのを利用しています。

以下は引数に画像アドレス配列を渡すと、一括して先読みしてくれる関数です。

function preload(imgs){
 for(var i = 0; i < imgs.length; i++){
   var imgObj = new Image();
   imgObj.src = imgs[i];
 }
}
preload(["sample1.jpg", "sample2.jpg", "sample3.jpg"]);

・・・が、これだけでは先読みの終了どころか、本当に先読みしてるのかもわかりません^^;

テストのために、先読みの経過を表示するコードを追加してみます。

<html>
<head>
<script type="text/javascript">
function preload(imgs){
  var objArray = [];
  for(var i = 0; i < imgs.length; i++){
    var imgObj = new Image();
    imgObj.src = imgs[i];
    objArray.push(imgObj);
  }
  var viewStatus = function(){
    var count = 0;
    var str = "";
    for(var i = 0; i < objArray.length; i++){
      if(objArray[i].complete) count++;
    }
    str += objArray.length + "件中" + count + "件完了";
    if(count == objArray.length){
      str += ":すべて完了しました。"
    }
    var viewElem = document.getElementById("view");
    if(viewElem) viewElem.innerHTML = str;
    if(count < objArray.length){
      setTimeout(viewStatus, 100);
    }
  };
  viewStatus();
}
function test(){
  preload(["http://f.hatena.ne.jp/images/fotolife/s/susie-t/20070407/20070407220053.jpg",
         "http://f.hatena.ne.jp/images/fotolife/s/susie-t/20070407/20070407215356.jpg",
         "http://f.hatena.ne.jp/images/fotolife/s/susie-t/20070407/20070407215255.jpg"]);
}
</script>
</head>
<body>
<div id="view"></div>
<button onclick="test();">preload</button>
</body>
</html>

preloadボタンを押すと先読みを開始します。で、状態を表示するのですが。。。これぐらいだとすぐに終わってしまいますね^^;大量の画像や重い画像を指定するとよく分かるのですが。手っ取り早く、存在しないアドレスを入れれば途中で止まりますが、ずっとsetTimeoutで回り続けますのでご注意を。また、キャッシュがあるとすぐに終わりますので、再度テストする場合はキャッシュを削除してください。

Imageオブジェクトのcompleteプロパティにより、画像読み込みが完了(=true)したかがわかります。これを利用しています。Imageオブジェクトのonloadイベントを使う手もありますが、ここでは省略させていただきます。(実際には、負荷の面から、1秒ごとにチェックするくらいが妥当な気がしてます。上記コードはテスト用なので0.1秒に設定しています。)