使用案例:
<div class="ocr-camera" v-show="showCamera"><div class="camera-head"><span>{{faceType }}人脸识别</span></div><div class="camera" id="camera"><video style="width: 100%; height: 100%; object-fit: cover" id="video" autoplay="autoplay" playsinline></video><div class="mask-view"><div>请将正脸移入框内</div></div></div><div class="camera-button"><span style="font-size: 15px" @click="cancel">取消</span><svg class="icon" aria-hidden="true" style="height: 65px; width: 65px" @click="takePicture"><use xlink:href="#icon-paizhao-copy"></use></svg><svg class="icon" aria-hidden="true" style="height: 40px; width: 40px" @click="switchCamera"><use xlink:href="#icon-qiehuanshexiangtou-copy"></use></svg></div><!--描绘video截图--><canvas v-show="showPicture" id="canvas" width="300" height="300" style="position: fixed; left: 10000px"></canvas></div>//mounted中this.video = document.getElementById("video");this.canvas = document.getElementById("canvas");this.context = this.canvas.getContext("2d");// 老的浏览器可能根本没有实现 mediaDevices,所以我们可以先设置一个空的对象if (navigator.mediaDevices === undefined) {navigator.mediaDevices = {};}// 一些浏览器部分支持 mediaDevices。我们不能直接给对象设置 getUserMedia// 因为这样可能会覆盖已有的属性。这里我们只会在没有getUserMedia属性的时候添加它。if (navigator.mediaDevices.getUserMedia === undefined) {navigator.mediaDevices.getUserMedia = function (constraints) {// 首先,如果有getUserMedia的话,就获得它var getUserMedia =navigator.webkitGetUserMedia || navigator.mozGetUserMedia;// 一些浏览器根本没实现它 - 那么就返回一个error到promise的reject来保持一个统一的接口if (!getUserMedia) {return Promise.reject(new Error("getUserMedia is not implemented in this browser"));}// 否则,为老的navigator.getUserMedia方法包裹一个Promisereturn new Promise(function (resolve, reject) {getUserMedia.call(navigator, constraints, resolve, reject);});};}
//methods中://开始拍照checkFace(typeName,type,index) {//默认使用前摄像头,强制使用后置摄像头如下设置// let constraints = {video: { facingMode: { exact: "environment" } }};if (this.stream) {this.stream.getTracks().forEach((track) => {track.stop();});}let constraints = {video: {facingMode: "user" } };navigator.mediaDevices.getUserMedia(constraints).then((stream) => {this.stream = stream;// 旧的浏览器可能没有srcObjectif ("srcObject" in this.video) {this.video.srcObject = stream;this.video.setAttribute('playsinline', true)this.video.play()} else {// 防止在新的浏览器里使用它,应为它已经不再支持了this.video.src = window.URL.createObjectURL(stream);this.video.setAttribute('playsinline', true)this.video.play()}this.video.onloadedmetadata = (e) => {this.video.play();};}).catch(function (err) {console.log(err.name + ": " + err.message);});this.showCamera = true;},//切换前后置switchCamera() {let constraints = {video: {facingMode: "user" } };if (this.isFrontCamera) {constraints = {video: {facingMode: {exact: "environment" },},};}if (this.stream) {this.stream.getTracks().forEach((track) => {track.stop();});}navigator.mediaDevices.getUserMedia(constraints).then((stream) => {this.stream = stream;this.isFrontCamera = !this.isFrontCamera;// 旧的浏览器可能没有srcObjectif ("srcObject" in this.video) {this.video.srcObject = stream;this.video.setAttribute('playsinline', true)this.video.play()} else {// 防止在新的浏览器里使用它,应为它已经不再支持了this.video.src = window.URL.createObjectURL(stream);this.video.setAttribute('playsinline', true)this.video.play()}this.video.onloadedmetadata = (e) => {this.video.play();};}).catch(function (err) {alert(err.name + ": " + err.message);console.log(err.name + ": " + err.message);});},takePicture() {//点击拍摄按钮,并生成照片文件console.log(this.video.videoWidth, this.video.videoHeight);this.canvas.width = this.video.videoWidth;this.canvas.height = this.video.videoHeight;//绘制画面this.context.drawImage(this.video,0,0,this.canvas.width,this.canvas.height);// canvas 转图片,再base64转流let blob = baseTofile(this.canvas.toDataURL("image/png"));function blobtoFile({type } = blob) {console.log(type, "type");return new File([blob], "人脸照片文件", {type });}this.showCamera = false;this.showDialog = true;//上传结果,掉接口识别,等待结果返回后,去掉弹框this.idNamePhotoCheck(blobtoFile(blob))},
踩坑记录1:
在浏览器中调用是正常的,但是在ios系统的微信内置浏览器中调用时,摄像头就唤醒不成功,原因:ios不会自动播放video
解决方案:
添加如下代码即可
//这个属性是ios微信浏览器设置可以让视频在小窗口内播放,也就是不是全屏播放this.video.setAttribute('playsinline', true)//播放this.video.play()
踩坑记录2:
当在A页面调用相机前置摄像头拍照后,通过路由跳转至B页面,此时再次调用相机后置摄像头黑屏或失败 ,原因:当前设备被占用
解决方案:
在A页面销毁时,如果相机设备被占用,就将它释放掉
在每次调用相机前,先关闭相机设备
destroyed(){if (this.stream) {this.stream.getTracks().forEach((track) => {track.stop();});}},