vue调用摄像头拍照,利用websocket和后端通信
vue调用摄像头拍照,利用websocket和后端通信
·
项目背景
公司最近客户要求做人脸验证,然后找了资料做了一个简单版,现在记录学习下。
实现原理
1,调用浏览器摄像头方法打开摄像头,然后利用canvas拍照转base64保存下来
2,利用websocket实时和后端通信, 每隔几秒向后端发送最新的拍的照片让后端对比,最后拿到返回的结果完成验证登录
<template>
<el-dialog
:visible.sync="dialogShow"
width="70%"
append-to-body
@close="stopCamera"
@open="openHeart"
>
<div class="compare-box">
<div class="video-box">
<div class="video-box1">
<div class="video-title1">
<video
id="videoCamera"
width="600"
height="460"
ref="videoElement"
autoplay
></video>
</div>
<div class="botn-box">
<el-button type="primary" @click="handleFile(1)"
>打开摄像头</el-button
>
<el-button type="primary" @click="handleFile(2)">拍照</el-button>
</div>
</div>
<div class="video-box2">
<div class="video-title1">
<canvas
id="canvasCamera"
width="600"
height="460"
ref="canvasElement"
></canvas>
</div>
<div class="botn-box">
<el-button type="primary" @click="handleFile(3)"
>确定上传</el-button
>
<el-button type="primary" @click="handleFile(4)">关闭</el-button>
</div>
</div>
</div>
</div>
</el-dialog>
</template>
<script>
export default {
data() {
return {
dialogShow: false,
photo: "", //拍照的
Loading: false,
videoElement: {
srcObject: null,
},
urlBase: "http://xxxxx", //地址
heartbeatInterval: null, // 保存心跳定时器的ID
heartbeatTimeout: 3000, // 心跳间隔时间
isConnected: false,
ws: null, // WebSocket连接
timerInter: null,
};
},
components: {},
computed: {},
created() {},
mounted() {
// this.initConnect();
},
methods: {
//按钮
handleFile(e) {
if (e == 1) {
this.startCamera();
} else if (e == 2) {
this.sendFrame();
} else if (e == 3) {
this.sendPhoto();
} else if (e == 4) {
this.stopCamera();
}
},
//打开摄像头
startCamera() {
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices
.getUserMedia({ video: true })
.then((stream) => {
this.$refs.videoElement.srcObject = stream;
this.videoElement.srcObject = stream;
this.$refs.videoElement.play();
// this.sendFrame();
})
.catch((error) => {
console.error("获取摄像头失败:", error);
});
} else {
window.alert("浏览器不支持getUserMedia");
}
},
//关闭摄像头和心跳
stopCamera() {
if (this.videoElement.srcObject) {
const tracks = this.$refs.videoElement.srcObject.getTracks();
tracks.forEach((track) => track.stop());
this.$refs.videoElement.srcObject = null;
this.videoElement.srcObject = null;
}
this.dialogShow = false;
const canvas = this.$refs.canvasCamera;
const context = canvas.getContext("2d");
context.clearRect(0, 0, canvas.width, canvas.height);
this.photo = "";
this.heartbeatInterval = null;
// 清除心跳定时器
clearInterval(this.heartbeatInterval);
this.timerInter = null;
// 定时器
clearInterval(this.timerInter);
},
openHeart() {
this.initConnect();
},
// 拍照
handlePhotograph() {
let canvas = this.$refs.canvasElement;
const context = canvas.getContext("2d");
context.drawImage(
this.$refs.videoElement,
0,
0,
canvas.width,
canvas.height
);
this.photo = canvas.toDataURL("image/jpeg"); // 将canvas内容转换为DataURL,即base64编码的图片数据UR
console.log(this.photo);
// this.sendPhoto(this.photo);
},
//开始拍照
sendFrame() {
this.handlePhotograph();
},
// 发送图片
sendPhoto(photo) {
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
this.ws.send(photo);
}
},
initConnect() {
this.startCamera();
var reqUrl = this.urlBase + "/camera";
let url = reqUrl.replace("http", "ws");
this.ws = new WebSocket(url); //websocket连接地址
this.ws.onopen = () => {
console.log("WebSocket连接已建立");
this.isConnected = true;
// 建立心跳定时器
this.heartbeatInterval = setInterval(() => {
if (this.ws.readyState === 1) {
// console.log(this.photo);
// this.ws.send(this.photo);
console.log("心跳开启");
}
}, this.heartbeatTimeout);
};
this.ws.onmessage = (event) => {
console.log(event.data, "接收到的信息");
if (event.data == "0") {
this.sendFrame();
} else if (event.data !== "连接成功") {
this.$emit("photoFile", event.data);
this.stopCamera();
} else {
}
};
this.ws.onerror = () => {
console.error("WebSocket连接发生错误");
this.ws.close();
};
this.ws.onclose = () => {
console.log("WebSocket连接已关闭");
this.ws.send("close");
this.isConnected = false;
// 清除心跳定时器
clearInterval(this.heartbeatInterval);
this.handleReconnect();
};
},
handleReconnect() {
console.log("WebSocket 断开连接,尝试重连...");
setTimeout(() => this.initConnect(), this.heartbeatTimeout);
},
},
beforeDestroy() {
if (this.heartbeatInterval !== null) {
this.ws.close();
this.heartbeatInterval = null;
// 清除心跳定时器
clearInterval(this.heartbeatInterval);
this.timerInter = null;
// 定时器
clearInterval(this.timerInter);
}
},
};
</script>
<style lang="less" scoped>
.video-box {
display: flex;
width: 1220px;
padding: 10px;
height: 580px;
margin: 0 auto;
align-items: center;
padding: 30px;
}
.video-box1 {
width: 600px;
}
.video-title1 {
width: 600px;
height: 470px;
border: 1px solid #409eff;
}
#videoCamera {
width: 100%; /* 或者其他尺寸 */
height: auto;
}
#canvasCamera {
width: 100%; /* 或者其他尺寸 */
height: auto;
}
.botn-box {
text-align: center;
margin-top: 20px;
}
.el-button {
// display: block;
margin: 0px auto;
text-align: center;
color: #fff;
background: #15bd9b;
border: none;
// border-radius: 36px;
cursor: pointer;
box-shadow: 0px 5px 25px rgba(0, 0, 0, 0.1);
}
.el-button:hover {
background-color: #088d72;
}
</style>
更多推荐
所有评论(0)