web网页调用电脑摄像头拍取照片
看不见看不见看不见 2024-07-16 09:03:02 阅读 88
之前用的是element-ui的上传图片组件,但是突然变更需求,要求相机拍摄,不让上传文件夹图片,并且上传至服务器
我们分为四步
第一步检查当前设备是否有摄像设备
window 身上自带了一个 navigator 属性,这个对象有一个叫做 mediaDevices 的属性是我们即将用到的。
<code>let navigator = window.navigator.mediaDevices;
let devices = await navigator.enumerateDevices();
console.log(navigator)
我们先看一下这个对象有哪些方法,你也许会看到下面的场景,会发现这个属性身上只有一个值为 null 的 ondevicechange 属性,不要怕,真正要用的方法其实在它的原型身上。
让我们点开它的原型属性,注意下面这两个方法,这是我们本章节的主角。
我们到这一步只是需要判断当前设备是否有摄像头,我们先调取 enumerateDevices 函数来查看当前媒体设备是否存在。它的返回值是一个 promise 类型,我们直接用 async 和 await 来简化一下代码。
<code> let navigator = window.navigator.mediaDevices;
let devices = await navigator.enumerateDevices();
console.log(devices);
从上图可以看出,我的电脑有两个音频设备和一个视频设备,那么我们就可以放下进行下一步了。
第二部获取摄像头
<code>//html部分
<video id="video" style="width: 600px" class="mb10"></video>code>
//js部分
navigator
.getUserMedia({
video: {
width: 500,
height: 500,
},
})
.then((mediaStream) => {
this.video = document.querySelector("video");
this.video.srcObject = mediaStream;
this.video.onloadedmetadata = function (e) {
video.play();
};
})
.catch((err) => {
console.log(err);
});
运行之后会显示
第三步点击拍摄按钮进行截取照片
<code>//拍摄按钮事件
clic() {
const canvas = document.createElement("canvas");
canvas.width = 200;
canvas.height = 200;
let ctx = canvas.getContext("2d");
ctx.drawImage(this.video, 0, 0, canvas.width, canvas.height);
let image = new Image();
let myImage = canvas.toDataURL("image/png");
image.src = canvas.toDataURL("image/png");
this.dataURLtoFile(myImage, "signature.png");
this.videoVisible = false; //相机展示画面是弹窗,这里是关闭弹窗
return image;
},
第四步将截取的图片转为base64字符串上传
dataURLtoFile(dataurl, filename) {
//将base64转换为文件,dataurl为base64字符串,filename为文件名(必须带后缀名,如.jpg,.png)
var arr = dataurl.split(","),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
let fileList = new File([u8arr], filename, { type: mime });
this.update(fileList); //图片上传
return new File([u8arr], filename, { type: mime });
},
//上传
update(file) {
let param = new FormData(); //创建form对象
param.append("file", file, file.name); //通过append向form对象添加数据
let url = process.env.VUE_APP_BASE_API + "/file/upload";
let headers = {
Authorization: "Bearer " + getToken(),
};
axios
.post(url, param, { headers: headers })
.then((response) => {
//这里是接口返回的数据用于展示
this.lvimage.push(response.data.data.url);
}
})
.catch((e) => {});
},
完整代码
html部分
//这里是上传图片以及图片展示标签
<div>
<el-image
class="upload_add"code>
v-for="url in lvimage"code>
:key="url"code>
:src="url"code>
>
</el-image>
<img
v-if="lvimage.length < 3"code>
src="../../../image/upload_add.png"code>
class="upload_add"code>
@click="uploadsuccess(1)"code>
/>
</div>
//弹窗里面显示拍摄的内容
<el-dialog :visible.sync="videoVisible">code>
<div class="flex flex-d a-center">code>
<video id="video" style="width: 600px" class="mb10"></video>code>
<el-button @click="clic" type="primary">拍摄</el-button>code>
</div>
</el-dialog>
JS部分
import axios from "axios";
//data里面定义的数据
videoVisible: false,
video: "",
lvimage: [],
//methods里面的方法
//点击上传按钮的事件
async uploadsuccess() {
this.videoVisible = true;
let navigator = window.navigator.mediaDevices;
let devices = await navigator.enumerateDevices();
console.log(devices);
navigator
.getUserMedia({
video: {
width: 500,
height: 500,
},
})
.then((mediaStream) => {
this.video = document.querySelector("video");
this.video.srcObject = mediaStream;
this.video.onloadedmetadata = function (e) {
video.play();
};
})
.catch((err) => {
console.log(err);
});
},
//点击拍摄按钮的事件
clic() {
const canvas = document.createElement("canvas");
canvas.width = 200;
canvas.height = 200;
let ctx = canvas.getContext("2d");
ctx.drawImage(this.video, 0, 0, canvas.width, canvas.height);
let image = new Image();
let myImage = canvas.toDataURL("image/png");
image.src = canvas.toDataURL("image/png");
this.dataURLtoFile(myImage, "signature.png");
this.videoVisible = false;
return image;
},
//将图片转为base64
dataURLtoFile(dataurl, filename) {
//将base64转换为文件,dataurl为base64字符串,filename为文件名(必须带后缀名,如.jpg,.png)
var arr = dataurl.split(","),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
let fileList = new File([u8arr], filename, { type: mime });
this.update(fileList); //图片上传
return new File([u8arr], filename, { type: mime });
},
//上传服务器
update(file) {
let param = new FormData(); //创建form对象
param.append("file", file, file.name); //通过append向form对象添加数据
let url = process.env.VUE_APP_BASE_API + "/file/upload";
let headers = {
Authorization: "Bearer " + getToken(),
};
axios
.post(url, param, { headers: headers })
.then((response) => {
if (response.data.code == 200) {
if (this.uplodebtn == 1) {
this.lvimage.push(response.data.data.url);
} else if (this.uplodebtn == 2) {
this.djimage.push(response.data.data.url);
} else {
this.zsimage.push(response.data.data.url);
}
}
})
.catch((e) => {});
},
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。