[React] React Webcam のカメラ映像を canvas に表示してみる
前回は img タグに表示してみました。今回は canvas タグに表示してみます。
img タグと比べると、少し工夫が必要になります。
準備
React Webcam のインストールなどはこちら。
カメラ映像から画像を取得して表示する
写真を撮るようなイメージで、ボタンを押したときの映像を canvas に表示してみます。
drawImage を使いたいので、new Image() で img要素を作り、onload を待つのがポイントです。
いつものように App.js を編集します。
import Webcam from "react-webcam";
import React, { useEffect, useRef, useState } from 'react';
import './App.css';
import Dropdown from "./components/Dropdown";
import Button from "./components/Button";
// const curried = (func, ...other) => (x => func(x, ...other));
function App() {
const [cameras, setCameras] = useState([]);
const [camera, setCamera] = useState(null);
const webcamRef = useRef(null);
const canvasRef = useRef(null);
useEffect(() => {
navigator.mediaDevices.enumerateDevices().then(mediaDevices => {
const devices = mediaDevices.filter(({ kind }) => kind === "videoinput");
setCameras(devices);
if (devices.length) {
setCamera(devices[0]);
}
})
}, [])
const handleClick = (cb) => {
const imageSrc = webcamRef?.current?.getScreenshot({ width: webcamRef.current.video.videoWidth, height: webcamRef.current.video.videoHeight });
if (!imageSrc) {
cb();
return;
}
const img = new Image();
img.src = imageSrc;
img.onload = () => {
const context = canvasRef?.current?.getContext('2d');
context?.drawImage(img, 0, 0);
cb();
}
};
return (
<>
<div className="bg-dark" style={{ minHeight: '100vh' }}>
<div className="p-5 text-center">
<Dropdown
className="mb-4"
variant="success"
title={camera ? camera?.label : 'カメラが見つかりませんでした。'}
items={cameras?.map(_camera => {
return {
children: _camera?.label,
className: _camera?.deviceId === camera?.deviceId ? 'disabled' : '',
onClick: () => setCamera(_camera),
};
})}
/>
<div className="d-flex justify-content-center align-items-center">
<Webcam
ref={webcamRef}
videoConstraints={{
width: 320,
height: 240,
deviceId: camera?.deviceId,
}}
className="border border-light"
style={{ width: 320, height: 240, boxSizing: 'content-box' }}
/>
<Button className="mx-4" onClick={handleClick}>→</Button>
<canvas
className="border border-light"
ref={canvasRef}
style={{ boxSizing: 'content-box' }}
width={320}
height={240}
/>
</div>
</div>
</div>
</>
);
}
export default App;
動かしてみます。
左がカメラ、右がcanvasタグ。(といっても見た目は img タグで作ったものと変わりません💦)
はい、できました。
ここにコードがないコンポーネントは、過去の記事にあります ('◇’)ゞ