JavaScriptでFileReaderを使った複数画像のプレビュー例
以前、「ブラウザで画像ファイルを選択した時にプレビュー表示する方法」という記事で、imgタグでプレビューする方法とcanvasでプレビュー方法の2種類について解説しました。
しかし、どちらもFileReaderを使っているわりに単体ファイルのプレビューしか考えられていない作りでしたので、今回は複数ファイルのプレビューについて補足です。
…というより、ぼく自身がちょっとハマってしまったので備忘録ですね。
HTMLの例
<p>■画像ファイルを選択してください。<br>
<input type="file" accept='image/*' multiple="multiple" onchange="loadImage(this);"></p>
<p id="preview"></p>
<style>
#preview img {
width:100px;
border:1px solid #cccccc;
}
</style>
解説
inputタグのtype=fileで複数ファイルの選択を許可するにはmultiple属性に"multiple"を指定します。
そして、プレビュー画像を表示する場所として、以前はimgタグのダミー(空の画像)を置いていましたが、今回は複数のimgタグを動的生成する必要があるため、IDに"preview"と付けたpタグをぽつんと置いているだけです。
CSSについては特に解説の必要がない気もしますが、プレビュー用のPタグの中に書かれたimgタグの大きさと枠線の指定ですね。
JavaScriptの例
<script>
function loadImage(obj)
{
document.getElementById('preview').innerHTML = '<p>プレビュー</p>';
for (i = 0; i < obj.files.length; i++) {
var fileReader = new FileReader();
fileReader.onload = (function (e) {
document.getElementById('preview').innerHTML += '<img src="' + e.target.result + '">';
});
fileReader.readAsDataURL(obj.files[i]);
}
}
</script>
解説
画像ファイルが選択された直後、このloadImage関数が呼び出されます。
引数に渡されたobjにファイル情報が入っているため、length=ファイルの数だけFileReaderクラスを作成し、readAsDataURLでファイルを読み込んでいます。
ポイントとしてはonloadの中ですかね。
前回は1ファイルだったので、fileReader.resultからファイルの中身を取り出していましたが、今回は複数あるため、onloadに渡す無名関数に引数 e を付けています。
この e.target に各ファイルのfileReaderが入ってくるため、e.target.resultをimgタグのsrcへセットしているわけです。
ちなみに innerHTML の中にimgタグをぐりぐり書く、なんて泥臭いやり方ではなく、
fileReader.onload = (function (e) {
var img = new Image();
img.src = e.target.result;
document.getElementById('preview').appendChild(img);
});
というようなエレガントな(?)やり方でも良いです。
ただ、どちらのほうが早いのか検証しているサイトがあり、innerHTMLにタグを書いたほうがかなり処理速度が早かったという結果が出ていたので、なんとなくタグで書いてみました。
その検証サイトとまったく同じ書き方というわけでもないので、そのうち自分でもちゃんとテストしてみたいですね。
実行結果
■画像ファイルを選択してください。
ファイル選択ボタンを押して、ダイアログから複数の画像ファイルを選ぶと、ダダダっと横並びに画像が表示されるはずです。
Webサーバーにファイルを送らずともこうしてクライアント側のJavaScript内だけで画像を処理できるとなにかと便利な場面があります。
単純にサーバーの負荷を軽減させることもできますし。
FileReaderさまさまですね。