Angular アプリケーションでデバイスのカメラを利用する方法を記載します。
Angular でのカメラ利用は Navigator.mediaDevices を利用すれば実現できます。
各ブラウザの対応状況については以下を参照下さい。 https://developer.mozilla.org/ja/docs/Web/API/Navigator/mediaDevices
1. <video>を用意する。
まずはHTML側に<video> を配置します。
そして、それぞれのElementをViewChildとして定義しておきます。
HTML
<video id="camera" #camera autoplay></video>
TS
@ViewChild('camera') camera?: ElementRef;
2. カメラを起動する処理を追加
次にカメラ起動に関する処理を記載します。
カメラを起動するには MediaDevices.getUserMedia() を利用します。
getUserMedia() の引数として MediaStreamConstraintsを定義しておきます。(引数に直接指定しても問題ないです。)
constraints: MediaStreamConstraints = { audio: false, video: { // environment : Rear camera / user : Self-view camera facingMode: 'environment' as VideoFacingModeEnum, }, };
<video>のsrcObjectに対し取得したMediaStreamをセットします。
カメラを起動する処理は AfterViewInit 等のタイミングで呼び出せば良いと思います。
if (!navigator.mediaDevices) { // 【navigator.mediaDevicesが取得できない場合の処理】 return; } navigator.mediaDevices .getUserMedia(this.constraints) .then((stream: MediaStream) => { if (this.camera) { this.camera.nativeElement.srcObject = stream; } }) .catch((error) => { // 【エラーが発生した場合の処理】 });
3. カメラを停止する処理を追加
OnDestroy 等カメラを停止したいタイミングで MediaStreamTrack.stop()をコールします。
if (this.camera?.nativeElement.srcObject) { const track = this.camera.nativeElement.srcObject.getTracks()[0] as MediaStreamTrack; track.stop(); }
4. 撮影処理を追加
これで基本的にカメラの起動/停止ができると思うので
後は撮影処理を実装すればカメラ機能として利用できます。
以下は撮影した画像をData URLとして取得する例です。(<canvas>を利用しています。)
HTML
<canvas id="canvas" #canvas></canvas>
TS
let width = this.camera?.nativeElement.clientWidth; let height = this.camera?.nativeElement.clientHeight; if (this.canvas) { const context = this.canvas.nativeElement.getContext('2d') as CanvasRenderingContext2D; this.canvas.nativeElement.width = width; this.canvas.nativeElement.height = height; const dataUrl = this.canvas.nativeElement.toDataURL( context.drawImage(this.camera?.nativeElement, 0, 0, width, height) ); this.dialogRef.close(dataUrl); }
注意点
ブラウザのカメラはセキュリティ上、基本的にHTTPSの場合かローカル(localhost)の場合のみ利用できるようになっており、 HTTPでは利用できません。(navigator.mediaDevices が取得できません。)
サンプル
以下サンプルとなります。
※ここではカメラをダイアログ表示(全画面)するものしMatDialogRefを入れています。
HTML
<video id="camera" #camera autoplay></video> <canvas id="canvas" #canvas></canvas>
※<button>や<img>等 撮影ボタンや必要に応じて閉じるボタン等を配置
TS
export class CameraComponent implements AfterViewInit, OnDestroy { @ViewChild('camera') camera?: ElementRef; @ViewChild('canvas') canvas?: ElementRef; constraints: MediaStreamConstraints = { audio: false, video: { // environment : Rear camera / user : Self-view camera facingMode: 'environment' as VideoFacingModeEnum, }, }; constructor(private dialog: MatDialog, private dialogRef: MatDialogRef<CameraComponent>) {} ngAfterViewInit(): void { this.startCamera(); } ngOnDestroy(): void { this.stopCamera(); } closeDialog() { this.dialogRef.close(); } startCamera() { if (!navigator.mediaDevices) { alert('camera is not supported.'); return; } navigator.mediaDevices .getUserMedia(this.constraints) .then((stream: MediaStream) => { if (this.camera) { this.camera.nativeElement.srcObject = stream; } }) .catch((error) => { // 【エラーが発生した場合の処理】 }); } stopCamera() { if (this.camera?.nativeElement.srcObject) { const track = this.camera.nativeElement.srcObject.getTracks()[0] as MediaStreamTrack; track.stop(); } } shoot() { let width = this.camera?.nativeElement.clientWidth; let height = this.camera?.nativeElement.clientHeight; if (this.canvas) { const context = this.canvas.nativeElement.getContext('2d') as CanvasRenderingContext2D; this.canvas.nativeElement.width = width; this.canvas.nativeElement.height = height; const dataUrl = this.canvas.nativeElement.toDataURL( context.drawImage(this.camera?.nativeElement, 0, 0, width, height) ); this.dialogRef.close(dataUrl); } } }