前端react实现调取摄像头并拍照进行上传包含绘制图片、base64图片转bold
写在前面,调取摄像头一定需要https协议下才可以,本地localhost也是可以的
首先判断当前设备是否可以调取摄像头
if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia) {
getUserMedia({video : {facingMode: "user", }}, success, error);//facingMode: "user" 为开启前置摄像头
} else {
alert('您的设备不支持访问用户媒体');
}
开启摄像头,获取视频流
function getUserMedia(constraints, success, error) {
if (navigator.mediaDevices.getUserMedia) {
//最新的标准API
navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error);
} else if (navigator.webkitGetUserMedia) {
//webkit核心浏览器
navigator.webkitGetUserMedia(constrains).then(success).catch(error);
} else if (navigator.mozGetUserMedia) {
//firfox浏览器
navigator.mozGetUserMedia(constraints, success, error);
} else if (navigator.getUserMedia) {
//旧版API
navigator.getUserMedia(constraints, success, error);
}
}
开启摄像头成功时回调方法
function success(stream) {
console.log(videoRef,stream);
const StreamTrack= typeof stream.stop === 'function' ? stream : stream.getVideoTracks()[0]; //这里需要定义一个全局变量记录这个值,方便在其他地方调用关闭摄像头
setMediaStreamTrack(StreamTrack); //使用useState存储,不是使用react的同学可以用其他方法存
try {
videoRef.current.srcObject = stream; //这里是react写法,videoRef是获取到的video元素,其他语框架的同学获取的video==videoRef.current;下面涉及videoRef的也一样
} catch (error) {
var CompatibleURL = window.URL || window.webkitURL;
videoRef.current.src = CompatibleURL.createObjectURL(stream);
}
videoRef.current.play();
}
开启摄像头成失败时回调方法
function error(error) {
console.log(`访问用户媒体设备失败${error.name}, ${error.message}`);
}
点击按钮执行拍照
function uploadImage(){
var context = canvasRef.current.getContext('2d'); //canvasRef同videoRef一样也是获取到的canvas元素,其他框架同学获取到的canvas==canvasRef.current;
canvasRef.current.width = videoRef.current.offsetWidth;
canvasRef.current.height = videoRef.current.offsetHeight ;
context.drawImage(videoRef.current, 0, 0, canvasRef.current.width, canvasRef.current.height); //绘制当前画面,形成图片
videoRef.current.pause(); //暂停摄像头视频流
mediaStreamTrack &&mediaStreamTrack .stop(); // 关闭摄像头 mediaStreamTrack 是上面setMediaStreamTrack方法存储得到的
var imgURL = canvasRef.current.toDataURL('image/jpeg', 60 / 100); //获取到的图片,这里的图片是base64位的,只需要base64图片的同学到这里就可以停止了
var $Blob = dataURLtoFile(imgURL) //将base64转换为blob,需要file进行上传
//这里可以执行你的上传方法($Blob )
}
dataURLtoFile 将base64转换为blob
function dataURLtoFile (dataurl, filename = 'file') {
let arr = dataurl.split(',')
let mime = arr[0].match(/:(.*?);/)[1]
let suffix = mime.split('/')[1]
let bstr = atob(arr[1])
let n = bstr.length
let u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], `${filename}.${suffix}`, {type: mime})
}
html部分
//非react框架同学忽略ref={videoRef} ref={canvasRef}
<video id="video" crossOrigin="anonymous" width="500" autoPlay ref={videoRef}></video>
<canvas id="canvas" ref={canvasRef}></canvas>
<div className="button" onClick={uploadImage}>{'确认拍摄'}</div>