调用本地摄像头进行拍照
摄像头取景框为圆形,照片为矩形
<template> <div> <div class="videoDiv"> <!-- 摄像头 --> <video id="videoCamera" style="border-radius: 50%" :width="videoWidth" :height="videoHeight" ></video> <!-- 幕布 --> <canvas id="canvasCamera" width="300" height="300" ></canvas> </div> <br /> <div v-if="imgSrc" class="imageDiv"> <!-- 图片 --> <img :src="imgSrc" class="img_camera" /> </div> <br /> <div class="buttonDiv"> <el-button type="primary" @click="openCamera">打开摄像头</el-button> <el-button type="primary" @click="takePhoto">拍照</el-button> <el-button type="primary" @click="closeCamera">关闭摄像头</el-button> </div> </div> </template> <script> //这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等) //例如:import 《组件名称》 from '《组件路径》'; export default { //import引入的组件需要注入到对象中才能使用 components: {}, data() { //这里存放数据 return { videoWidth: 300, videoHeight: 300, imgSrc: "", thisCanvas: null, thisVideo: null, thisContext: null, }; }, //方法集合 methods: { //打开摄像头 openCamera() { //_this只是一个变量名,this代表父函数,如果在子函数还用this,this的指向就变成子函数了,_this就是用来存储指向的 //函数中还有子函数的,用 _this 来代表父函数中的 this var _this = this; //定义幕布 this.thisCanvas = document.getElementById("canvasCamera"); //设置环境为2d this.thisContext = this.thisCanvas.getContext("2d"); //定义相机 this.thisVideo = document.getElementById("videoCamera"); //判断浏览器是否支持mediaDevices if (navigator.mediaDevices === undefined) { //不支持,设置一个空对象 navigator.mediaDevices = {}; } //判断浏览器是否缺少getUserMedia属性 if (navigator.mediaDevices.getUserMedia === undefined) { //缺少getUserMedia属性,添加该属性 navigator.mediaDevices.getUserMedia = function (constraints) { //如果现存 getUserMedia,将其获取 var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.getUserMedia; //如果浏览器不支持,返回错误信息 if (!getUserMedia) { return Promise.reject( new Error("getUserMedia is not implemented in this browser") ); } //否则,使用Promis将调用方法包装到旧的getUserMedia中 return new Promise(function (resolve, reject) { getUserMedia.call(navigator, constraints, resolve, reject); }); }; } //定义 constraints var constraints = { audio: false, video: { width: this.videoWidth, height: this.videoHeight, transform: "scaleX(-1)", }, }; navigator.mediaDevices .getUserMedia(constraints) .then(function (stream) { //判断浏览器中是否有 srcObject if ("srcObject" in _this.thisVideo) { //浏览器中存在 _this.thisVideo.srcObject = stream; } else { //浏览器中不存在,因其正在被弃用,避免在新浏览器中使用它 _this.thisVideo.src = window.URL.createObjectURL(stream); } _this.thisVideo.onloadedmetadata = function (e) { _this.thisVideo.play(); }; }) .catch((err) => { console.log(err); }); }, //关闭摄像头 closeCamera() { this.thisVideo.srcObject.getTracks()[0].stop(); }, //拍照功能 takePhoto() { var _this = this; //点击canvas画图 _this.thisContext.drawImage(_this.thisVideo, 0, 0, 300, 300); //获取图片base64连接 var image = this.thisCanvas.toDataURL("/image/png"); _this.imgSrc = image; this.$emit("refreshDataList", this.imgSrc); }, //base64转文件 dataURLtoFile(dataurl, fileName) { var arr = dataurl.split(","); var mime = arr[0].match(/:(.*?);/)[1]; var bstr = atob(arr[1]); var u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new File([u8arr], fileName, { type: mime }); }, }, //生命周期 - 创建完成(可以访问当前this实例) created() {}, }; </script> <style scoped> /* @import url(); 引入公共css类 */ .videoDiv { text-align: center; height: 500; } .imageDiv{ text-align: center; height: 400; } .buttonDiv { text-align: center; } </style>