スマホなどでカメラを操作する際に、リアとフロントのカメラをJavaScriptで切り替える簡単なサンプルです。
カメラのフロントとリアを切り替える
実行例
以下から実際のサンプルをお試しいただけます。 miku3.net
- フロント、リアカメラが両方の付いた端末で実行してください。
- 要はスマホですね。
- 例えばフロントしか無い場合は、切り替えたタイミングでエラー表示が出ます
初回のアクセス時にWebブラウザから、このサイトにカメラの操作を許可して良いか聞かれますので「許可」ボタンをクリックしてください。「ブロック」ボタンを押すと設定を変更するのにメニューの少し深いところに潜る必要がありますのでご注意を。
サンプルコード
CSSは別ファイルにしています。
<!DOCTYPE html> <html> <head> <meta charset="utf8"> <title>Camera Test</title> <link rel="stylesheet" href="style.css" type="text/css" media="all"> </head> <body> <div id="contents"> <!-- カメラ映像 --> <video id="camera" width="640" height="480"></video> <!-- 切り替えボタン --> <button type="button" id="btn-toggle"> <img src="icon/retweet-solid.svg" width="64" height="64"> </button> </div> <script> //--------------------------------------------- // グローバル変数 //--------------------------------------------- // カメラのデフォルト設定 var CONSTRAINTS = { audio: false, video: { width: 640, height: 480, facingMode: null // どのカメラを利用するか // facingModeには最終的に以下のいずれかの値を入れる // facingMode: "user" // フロントカメラを利用する // facingMode: { exact: "environment" } // リアカメラを利用する } }; // 現在のStream var curSTREAM = null; //--------------------------------------------- // [event] ページ読み込み完了 //--------------------------------------------- window.onload = () => { const video = document.querySelector("#camera"); let useFront = true; // フロントカメラ:true, バックカメラ:false // 縦横の解像度を調整 adjustCameraSize(video, 640, 480); // カメラと同期開始 syncCamera(video, useFront); useFront = !useFront; // boolean値を反転 //------------------------------- // [event] 切り替えボタン押下 //------------------------------- document.querySelector("#btn-toggle").addEventListener("click", ()=>{ syncCamera(video, useFront); useFront = !useFront; // boolean値を反転 }); }; /** * カメラを<video>と同期 * * @param {object} video * @param {boolean} [is_front=true] */ function syncCamera(video, is_front=true){ // 前後カメラの設定 CONSTRAINTS.video.facingMode = (is_front)? "user":{ exact: "environment" }; // すでにカメラと接続していたら停止 if( curSTREAM !== null ){ curSTREAM.getVideoTracks().forEach( (camera) => { camera.stop(); }); } // カメラと接続する navigator.mediaDevices.getUserMedia(CONSTRAINTS) .then( (stream) => { curSTREAM = stream; // 前後の切り替え用に保持 // <video>とStremaを接続 video.srcObject = stream; video.onloadedmetadata = (e) => { video.play(); }; }) .catch( (err) => { console.log(`${err.name}: ${err.message}`); alert("カメラとの接続時にエラーが発生しました"); }); } /** * 解像度に合わせて<video>サイズを調整する * * @param {object} video * @param {integer} longside 長辺のピクセル数 * @param {integer} shortside 短辺のピクセル数 **/ function adjustCameraSize(video, longside, shortside){ if( window.innerWidth < window.innerHeight ){ // getUserMediaに食わせる値 CONSTRAINTS.video.width = shortside; CONSTRAINTS.video.height = longside; // videoタグのサイズ video.style.width = shortside; video.style.height = longside; } } </script> </body> </html>
解説
フロントとリアの切り替え
カメラと接続する際にnavigator.mediaDevices.getUserMedia()
を利用するわけですが、このとき
facingMode
の値にuser
を指定すればフロントカメラ、{ exact: "environment" }
ならリアカメラとなります。
フロントカメラ
navigator.mediaDevices.getUserMedia({ audio: false, video: { width: 640, height: 480, facingMode: "user" } })
リアカメラ
navigator.mediaDevices.getUserMedia({ audio: false, video: { width: 640, height: 480, facingMode: { exact: "environment" } } })
切り替えその前に
切り替え自体は簡単なんですが、注意すべきは直前のStreamを停止してから接続し直す点です。どんどんStreamが開いちゃいますからねw
ここではグローバル変数curSTREAM
にstreamを記録しておき、
navigator.mediaDevices.getUserMedia(CONSTRAINTS) .then( (stream) => { curSTREAM = stream; // 前後の切り替え用に保持
2回目以降の接続時には、Streamをstop()
で事前に停止させます。
if( curSTREAM !== null ){ curSTREAM.getVideoTracks().forEach( (camera) => { camera.stop(); }); }
素材
- Fontawesome