こんにちは!ケインコスゲ(@keinkosuge)です。
今回は、JavaScriptでFileAPIとFile Reader APIを扱う方法についてご紹介です。
File APIもFileReader APIも正直、真新しい技術ではないのですが、今回たまたま「スマホで画像撮影→撮影した画像をプレビュー表示」する実装方法を人に教える機会がありました。
その時、File APIのことを説明するのに「スマホで画像撮影→撮影した画像をプレビュー表示」がわかりやすい事例だなと思ったので、今回このブログ記事を書いてみることになりました。
目次
File APIとFile Reader APIをスマホで画像撮影→プレビュー表示までの完成形
それでは、今回の記事を通じて制作する「File APIとFile Reader APIを使ってスマホで画像撮影→撮影した画像をプレビュー表示」までを行うコードの完成事例からご紹介したいと思います!
上記の「Result」で表示されている部分を、PCからでもスマホからでもいいので、お手元にある画像を選択してみてください!
スマホからの場合は、以下にあげるように、写真を撮影→プレビュー表示まで簡単にできるようになっています。
HTML部分の説明! input type=”file”にaccept属性をつけるだけでスマホで撮影したカメラをそのまま反映できるHTML Media Captureも紹介!
ここからは、上記に掲載した完成事例のサンプルコードを見ながら解説していきたいと思います!
それではまずはHTML部分から説明していきますので、一緒に書いてみましょう!
上記画像にも掲載したように、今回はinput type=”file”に、スマホで撮影した画像を反映させて、反映させた画像をプレビュー表示するというものを制作していきます。
input type=”file”は、何かしらのファイルを選択して、SNSのプロフィール画像を設定したり、お問い合わせフォームからメール送信する際に何かしらのファイルを添付したりする際に用いられるHTMLのタグです。
そして今回の制作物の特徴である、「スマホで撮影した画像を使う」という部分を実現させているのが、input type=”file”についているaccept属性に書かれた部分になります。
HTML5 ROCKSにも掲載されていますが、accept属性の中身を「accept=”image/*;capture=camera”」とすることよって、
- アップすることができるファイルの種類を画像に限定する(「image/*」と書かれた部分)
- スマホで撮影したり、スマホに既に入っている画像をそのまま使用
以上のようなことができるようになります!便利ですよね!
「image/*」と書かれた部分を「video/*」に変更することによって、画像ではなく動画のみを反映させることができるようになりますし、「accept=”audio/*;capture=microphone”」と記載することによって、音声記録も可能になるようです。
ここまで紹介しているaccept属性の部分を「HTML Media Capture」と呼ぶそうですが、HTML周りのことを色々と策定しているW3Cという期間も、HTML Media Captureの利用を推奨するようになっていたのですが、ブラウザ対応状況を調べてみると概ねスマホブラウザのみOK、PCブラウザにおいてはまだ対応があまりなされていないという状況でした。
今回の制作事例のように、スマホ向けの何かを作るという場合の利用にのみとどめた方がいいのかもしれないですね!
JavaScriptの説明!File APIとFileReader APIとはそれぞれ何者か
さて、HTML部分の解説・技術の準備ができたところで、いよいよJavaScript部分の説明に入っていきたいと思います。
changeイベントとは??スマホで撮影した画像がinput type=”file”部分に反映されたら何かのプログラムが実行されるという動きを実装する
まず、「スマホで撮影した画像を選択し、撮影画像をinput type=”file”に反映させたら何かのプログラムを実行させる」という部分の実装を見ていきます。
この部分は、changeイベントを使って実装することが可能です。
document.querySelector("#file").addEventListener("change", function(e){
//ここにinput type="file"に画像が反映時に実行したいプログラムを書く
});
該当部分は上記の通りです。
inputタグに関するものは、値が変わったときには必ず「change」イベントが発生されるようになっています。たとえば、
- input tyoe=”text”の入力値を変更
- セレクトボックス(プルダウン)で選択する内容を変更
- ラジオボタンで選択している値を変更
した際にchangeイベントが発生します。
該当のHTMLにはid=”file”がついているので、「id=”file”がついているHTMLタグの中身の値が変わった時に」というイベントの定義は、上記のようなコードで可能になるわけです。
File APIとは??
さて、次にFile APIについて見ていきたいと思います。
繰り返しますが、今回のサンプルでは、スマホで撮影した画像をinput type=”file”に反映させてプレビュー表示させるというサンプルを作っています。
今回の事例でいうと「スマホで撮影した画像をinput type=”file”に反映させたときに、プログラム側でそのファイルに関する基本的な情報を確認することができる」、その仕組みと決まりごとを、File APIと言います。
例えば上記の画像を見ていただくとわかるように、1枚の画像も様々なデータを持っています。
画像のサイズ、名前など様々な情報があるわけですが、これらのデータをプログラムでどのように書くと使用できるようになるのか、その決まりごととなっているのがfile APIだと思ってください。
document.querySelector("#file").addEventListener("change", function(e){
const file = e.target.files[0];
console.log(file);//input type="file"に反映された画像に関するデータが表示
});
JavaScriptコードを上記のように変更・追記してみます。その上で、input type=”file”に何か適当な画像を反映させてみます。
すると、Consoleパネルなどで、「画像のファイル名・サイズ・形式」などが確認できます。
上記に掲載した画像のように、例えばファイルの画像名を扱いたいならば「e.target.files[0].size」と記述する、などのような決まりごとがまさにFile APIの部分になります。
document.querySelector("#file").addEventListener("change", function(e){
const file = e.target.files[0];//反映されたfile情報に相当
if(file.size > 180000){
alert("容量が大きすぎます。180KB以下の画像を選択してください");
return;
}
console.log(file);//input type="file"に反映された画像に関するデータが表示
});
上記にサンプルコードを掲載しましたが、File APIを使えば、一定の容量を越えた画像ファイルをすることができないようにする実装も簡単に行うことができます。
くどいようですが、このようにinput type=”file”に反映された様々な情報を取得するためのルール・決まりごとをFile APIというのだと思ってください!
FileReader APIとは??
ここまでは、File APIを使ってinput type=”file”に反映させた画像の基本的な情報を取得するというところまでを説明してみました。
しかし、このままでは画像のプレビュー表示を行うことはできません。なぜなら、画像そのものの情報(どんな内容の画像なのか)を取得することがまだできていないからです。
ここで出てくるのがFileReader APIです。
document.querySelector("#file").addEventListener("change", function(e){
const file = e.target.files[0];
const filereader = new FileReader();//FileReader APIを扱うための決まりごととなる部分を複製(オブジェクトのインスタンス化)
filereader.addEventListener("load",function(event){
//ここにFileの内容が実際に読み込まれた際に行いたいプログラムの内容を書く
});
});
File Reader APIを使うことによって、実際に画像の内容を読み込むことができます。
上記に掲載したコードのように、FileReader APIを使いますよという宣言をまず行い、その後にFileReader APIを使って実際に画像の内容が読み込まれた後に行いたいプログラムを定義していきます
document.querySelector("#file").addEventListener("change", function(e){
const file = e.target.files[0];
const filereader = new FileReader();//FileReader APIを扱うための決まりごととなる部分を複製(オブジェクトのインスタンス化)
filereader.addEventListener("load",function(event){
//ここにFileの内容が実際に読み込まれた際に行いたいプログラムの内容を書く
document.querySelector('#preview').setAttribute("src", event.target.result);
});
});
今回の目的は、「input type=”file”に反映された画像の情報をプレビュー表示する」でしたので、プレビュー表示をする部分のコードを、上記のようにloadイベントの中に記載すればOKです!
ここまではまだ「実際に画像がinput type=”file”に反映された場合に、実行したいプログラムの内容を定義」しているだけなので、最後に実際の画像内容を読み込むための記述を追加します!
document.querySelector("#file").addEventListener("change", function(e){
const file = e.target.files[0];
const filereader = new FileReader();
filereader.addEventListener("load",function(event){
document.querySelector('#preview').setAttribute("src", event.target.result);
});
filereader.readAsDataURL(file);//実際にファイル内容を読み込むための記述
});
最後に、filereader.readAsDataURL(file)という記述を追加しましたが、ここは「どんな風に画像の内容を読み込みするのか」を指定している部分になります。
詳しくは上記MDN上のページに書かれているので、どんな画像の内容の読み込み方法があるのか気になる場合は、参照してみてくださいね!
以上で、実装終了です!
まとめ
ということで今回は、File APIとFileReader APIをスマホで画像撮影→プレビュー表示までの流れで学ぶというテーマでお送りしました。
実際の事例を交えながらやってみると「File API」がどの部分に相当して、「FileReader API」がどの部分に相当するのかがイメージしやすくなるのではないかと思い、今回のテーマを用いたのですが、いかがでしたでしょうか。
File APIとFileReader APIを組み合わせれば、ブラウザ上で画像をリサイズ→ダウンロードするようなアプリも簡単に作れるようになるので、結構便利です。
ぜひ実装してみてください!