177 lines
5.8 KiB
Python
177 lines
5.8 KiB
Python
<template>
|
||
<div class="faceLoginWrap">
|
||
<div style="height:fit-content;">
|
||
<div class="video-box">
|
||
<video id="video" width="600" preload autoplay muted></video>
|
||
<canvas id="canvas" width="600" height="500"></canvas>
|
||
</div>
|
||
<canvas id="screenshotCanvas" width="600" height="500"></canvas>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
<script>
|
||
import {clockRecord} from '@/api/hrm'
|
||
import tracking from '@/assets/tracking/build/tracking-min.js';
|
||
import '@/assets/tracking/build/data/face-min.js';
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
video: null,
|
||
screenshotCanvas: null,
|
||
uploadLock: false // 上传锁
|
||
}
|
||
},
|
||
mounted() {
|
||
this.openTheCamera();
|
||
},
|
||
methods: {
|
||
openTheCamera() {
|
||
this.$nextTick(function () {
|
||
let _this = this;
|
||
this.video = document.getElementById('video');
|
||
// 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象
|
||
if (navigator.mediaDevices === undefined) {
|
||
navigator.mediaDevices = {}
|
||
}
|
||
// 一些浏览器实现了部分mediaDevices,我们不能只分配一个对象
|
||
// 使用getUserMedia,因为它会覆盖现有的属性。
|
||
// 这里,如果缺少getUserMedia属性,就添加它。
|
||
if (navigator.mediaDevices.getUserMedia === undefined) {
|
||
navigator.mediaDevices.getUserMedia = function (constraints) {
|
||
// 首先获取现存的getUserMedia(如果存在)
|
||
let getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.getUserMedia;
|
||
// 有些浏览器不支持,会返回错误信息
|
||
// 保持接口一致
|
||
if (!getUserMedia) {
|
||
return Promise.reject(new Error('getUserMedia is not implemented in this browser'))
|
||
}
|
||
// 否则,使用Promise将调用包装到旧的navigator.getUserMedia
|
||
return new Promise(function (resolve, reject) {
|
||
getUserMedia.call(navigator, constraints, resolve, reject)
|
||
})
|
||
}
|
||
}
|
||
let 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.video) {
|
||
_this.video.srcObject = stream
|
||
} else {
|
||
// 避免在新的浏览器中使用它,因为它正在被弃用。
|
||
_this.video.src = window.URL.createObjectURL(stream)
|
||
}
|
||
_this.video.onloadedmetadata = function () {
|
||
_this.video.play();
|
||
};
|
||
_this.init();
|
||
}).catch(err => {
|
||
console.log(err)
|
||
})
|
||
});
|
||
},
|
||
// 初始化设置
|
||
init() {
|
||
this.screenshotCanvas = document.getElementById('screenshotCanvas');
|
||
let canvas = document.getElementById('canvas');
|
||
let context = canvas.getContext('2d');
|
||
|
||
// 实例化tracker对象
|
||
let tracker = new window.tracking.ObjectTracker('face');
|
||
tracker.setInitialScale(4);
|
||
tracker.setStepSize(2);
|
||
tracker.setEdgesDensity(0.1);
|
||
//tracker对象和标签关联
|
||
window.tracking.track('#video', tracker, {
|
||
camera: true
|
||
});
|
||
let _this = this;
|
||
//添加事件
|
||
tracker.on('track', function (event) {
|
||
// 检测出人脸 绘画人脸位置
|
||
context.clearRect(0, 0, canvas.width, canvas.height);
|
||
// 给每个人脸绘制对应的框
|
||
event.data.forEach(function (rect) {
|
||
context.strokeStyle = '#0764B7';
|
||
context.strokeRect(rect.x, rect.y, rect.width, rect.height);
|
||
// window.plot(rect.x, rect.y, rect.width, rect.height+20);
|
||
// 避免重复发送请求
|
||
if (!_this.uploadLock) {
|
||
_this.uploadLock = true;
|
||
// 上传图片
|
||
_this.screenshotAndUpload();
|
||
}
|
||
});
|
||
});
|
||
},
|
||
// 上传图片
|
||
screenshotAndUpload() {
|
||
let that = this;
|
||
// 绘制当前帧图片转换为base64格式
|
||
let canvas = this.screenshotCanvas;
|
||
let video = this.video;
|
||
let ctx = canvas.getContext('2d');
|
||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
|
||
let base64Img = canvas.toDataURL('image/jpeg');
|
||
let img = base64Img.split(',')[1];
|
||
let imgData = {base64: img,tolerance:0.42};
|
||
clockRecord(imgData).then((res) => {
|
||
debugger;
|
||
if (res.code === 200 && res.data.id) {
|
||
this.$message.success(res.data.name + '签到成功!');
|
||
setTimeout(() => {
|
||
that.uploadLock = false;
|
||
}, 5000)
|
||
} else {
|
||
that.uploadLock = false;
|
||
}
|
||
}).catch(() => {
|
||
// 打开锁
|
||
that.uploadLock = false;
|
||
});
|
||
},
|
||
closeCamera() {
|
||
this.video.srcObject.getTracks()[0].stop();
|
||
},
|
||
}
|
||
}
|
||
</script>
|
||
<style scoped>
|
||
.faceLoginWrap{
|
||
/*padding: 50px;*/
|
||
/*width: 600px;*/
|
||
/*height: 600px;*/
|
||
/*background: #000000;*/
|
||
margin:50px auto 0 auto;
|
||
/*box-sizing: border-box;*/
|
||
}
|
||
|
||
#screenshotCanvas {
|
||
display: none;
|
||
}
|
||
|
||
.video-box {
|
||
width: 600px;
|
||
height: fit-content;
|
||
margin: auto;
|
||
position: relative;
|
||
}
|
||
|
||
#video {
|
||
object-fit: fill;
|
||
-webkit-border-radius: 250px;
|
||
-moz-border-radius: 250px;
|
||
border-radius: 250px;
|
||
}
|
||
|
||
video, canvas {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
}
|
||
</style>
|