最近、Webアプリでカメラで撮ったものをWebAPIに投げたい、というのを何度か書いており、ついでにここに書いておきます。
PC
Media Streams APIを使って画像に変換する、ということにしました。
お役立ちドキュメントは以下です。
- https://developer.mozilla.org/ja/docs/Web/API/MediaDevices/getUserMedia
- https://developer.mozilla.org/ja/docs/Web/API/MediaDevices/enumerateDevices
雑に使うだけなら、enumerateDevices
は使わなくてもできますが、カメラを選ばせたいときは必要です。
また、上記のサンプルコードには書いてないですが、MediaStreamもリソースなのでちゃんと閉じる処理を書く必要があります。
具体的には、Mediastream#getTracksでMediaTrackを複数取得し、その後、MediaTrack#stopを呼ぶ感じです。
以下、Vueでそれっぽく実装したデモです。
ボタンを押したらCanvasに転写して画像データをURLに変換してImageタグを埋め込むだけです。
Demo: https://jsfiddle.net/4r8djy7c/
カメラが無いデバイスだと、mediaDevices.getUserMedia
で失敗するので、catchでいい感じにやりましょう。
SmartPhone
なんでPCとSmartPhoneを分けているかというと、SmartPhoneではうまく動作しなかったからです。頑張って書いたのに!
同じコードで動かず悩みましたが、別のワークアラウンドを使う事にしました。
以下のように<input type="file">
へcapture
属性を付けるとカメラで撮影したものをファイルとして扱えるようになります。
一応、すぐに試せるのがあったほうが良いと思い、簡単ですが動くやつを書きました。モバイル用にQRも乗っけておきます
Demo: https://jsfiddle.net/fw4jyn95/1/
https://fiddle.jshell.net/fw4jyn95/1/show/
これはW3CのDevice and Sensors WGの成果物で、現状、SmartphoneのAndroidやiPhone等で動作します。ステータスは・・・どうなんだろう?
また、capture
属性にはenvironment
(リアカメラ)かuser
(フロントカメラ)のいずれかを与えます。大半はenvironment
で問題ないですが、地鶏アプリならuser
という感じです。
なお、PCで使ってたMediaStream APIでも同様にどちらのカメラを使うようにするか設定ができます。
このおかげで、導線はボタンを用意するだけで、UIもカメラの許可/拒否もデバイスに丸投げ出来ます。良いですね。
次に、<input type="file">
の見た目が良くないのでボタンにしたい!となると思います。
そうなると、display: none
で隠して別のボタンからclickさせる等をするのですが、もしcreateElementを使う方法でやる場合は、以下の点も注意してください。
iOS-Safariで<input type="file">
のChangeイベントを拾うときの注意
https://qiita.com/fukasawah/items/b9dc732d95d99551013d
蛇足ですが、PCとSmartphoneの判断をUserAgentで行う場合、wootheeが便利です。
https://github.com/woothee/woothee