スマホなどでカメラを操作する際に、リアとフロントのカメラをJavaScriptで切り替える簡単なサンプルです。
目次
カメラのフロントとリアを切り替える
実行例
以下から実際のサンプルをお試しいただけます。
- フロント、リアカメラが両方の付いた端末で実行してください。
- 要はスマホですね。
- 例えばフロントしか無い場合は、切り替えたタイミングでエラー表示が出ます
初回のアクセス時に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
参考ページ
このブログを応援する
お寄せいただいたお気持ちは全額サーバ代や次の記事を執筆するための原資として活用させていただいております。この記事が参考になった場合などぜひご検討ください。