画像を画像サーバーにアップすることはよくあります。全容の画像サーバー出なくても、時間の経過につれ、元々あった画像がなくなっている場合があります。この場合は、ただ画像が無いことをユーザーに見せるか、それとも、画像がないこと自体もユーザーに知らせないのか、二者択一になります。もし後者を選ぶ場合であれば、大体3種類の方法があります。
方法1
一つはサーバー再度でチェックを行います。今実在している画像のみをブラウザに送ります。この方法は明らかに大量画像に対応できません。負担がサーバーに大きく集中し、現実的な良策とは言えません。
方法2
残りの二種類の方法はどっちもクライアント再度でJavaScriptで画像の確認を行います。中により簡単な、いわば中間策は、<img>タグのonerrorイベントに自身を削除させるコードを入れさせます。例えばこのコード:
1 |
<img src="..." onerror="this.parentNode.removeChild(this);"> |
このコードはシンプルで、シンプル過ぎて、ロード中の仮画像は表示されます。せめて、この仮画像は出てほしくないなぁ~と思うなら、ロードに結果が出るまでは透明にするのが一つの方法です。例えば、下記のコードです。
1 2 3 4 |
<img style="opacity: 0" onerror="this.parentNode.removeChild(this);" onload="this.style.opacity=1;"> |
方法3
方法2のバージョンアップとして考えてみれば、画像が成功にロードできる場合に限ってこの画像を実行しましょう。つまり、方法2のonloadに現在画像をページ上の他所に実装するコードを入れます。しかし、ここはこのやり方をあえてせず、この機能をJavaScriptのクラスに清潔にまとめたいと思います。しかも、もうちょっと制御を入れます。
仮に、画像一覧があります。順番どおりにユーザーに見せたいです。しかし、単純な方法2を改装するところで、これは達成し辛いというわけではないですが、ページ上で多少ゴチャゴチャになるところがでてくるかもしれません。このため、コードをカプセル化します。下記のようなコードになます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
var ImageExists=function (urls,onImgReady) { this.imgs=[]; this.urls=urls; if (typeof onImgReady=='function') this.onImgReady=onImgReady; else this.onImgReady=function () {}; this.idxNextToReport=0; this.run=function () { var container=this; for (var i=0;i<this.urls.length;i++) { var img=new Image(); var imginfo; imginfo={ "status": "unknown", "obj" : img, }; this.imgs.push(imginfo); img.index=i; img.onload=function () { container.imgs[this.index].status='ok'; container._someImageReady(); }; img.onerror=function () { container.imgs[this.index].status='err'; container._someImageReady(); }; img.src=this.urls[i]; } }; this._someImageReady=function () { while (this.idxNextToReport<this.imgs.length) { if (this.imgs[this.idxNextToReport].status=="unknown") break; if (this.imgs[this.idxNextToReport].status=='ok') this.onImgReady(this.imgs[this.idxNextToReport].obj.src); this.idxNextToReport++; } }; }; |
このコードでは、実在している画像のみをコーラーに報告します。同時に、報告の順は画像URLの順です。使用方法に関しては、下記のサンプルをご参考下さい。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
var urls=[ "http://www.graphicstock.com/eiwoffjgh.jpg", "http://cdn.1001freedownloads.com/icon/thumb/387305/File-Adobe-Dreamweaver-JavaScript-icon.png", "http://www.freeimages.com/eiwofjgh.jpg", "http://thinketg.com/wp-content/uploads/2014/09/js.png", "http://pixabay.com/eiwoffjgh.jpg", "http://www.stockfreeimages.com/eiwoffjgh.jpg", "http://www.dreamstime.com/eiwoffjgh.jpg", "http://www.antrromet.com/img/icon_js.png", "http://www.mackenziearmstrongcreative.com/images/jsIcon.png" ]; var IR=new ImageExists(urls,function (url) { var img=document.createElement('IMG'); img.src=url; document.body.appendChild(img); }); IR.run(); |