<template> <div class="camera_outer"> <video id="videoCamera" :width="videoWidth" :height="videoHeight" autoplay /> <canvas id="canvasCamera" :width="videoWidth" :height="videoHeight" style="display: none" /> </div> </template> <script> import { faceLogin } from '@/api/login' import { setToken } from '@/utils/auth' export default { name: 'FaceLogin', data() { return { videoWidth: 414, videoHeight: 736, thisCancas: null, thisContext: null, thisVideo: null, faceList: [], tryFaceLogin: true, // 尝试人脸登录 tryCount: 0 } }, mounted() { this.videoWidth = document.body.clientWidth this.videoHeight = document.body.clientHeight this.getCompetence() }, methods: { // 调用权限(打开摄像头功能) getCompetence() { const _this = this this.thisCancas = document.getElementById('canvasCamera') this.thisContext = this.thisCancas.getContext('2d') this.thisVideo = document.getElementById('videoCamera') this.videoHeight = _this.thisVideo.clientHeight this.videoWidth = _this.thisVideo.clientWidth // 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象 if (navigator.mediaDevices === undefined) { navigator.mediaDevices = {} } // 一些浏览器实现了部分mediaDevices,我们不能只分配一个对象 // 使用getUserMedia,因为它会覆盖现有的属性。 // 这里,如果缺少getUserMedia属性,就添加它。 if (navigator.mediaDevices.getUserMedia === undefined) { navigator.mediaDevices.getUserMedia = function(constraints) { // 首先获取现存的getUserMedia(如果存在) const getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.getUserMedia // 有些浏览器不支持,会返回错误信息 // 保持接口一致 if (!getUserMedia) { alert('error') 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) }) } } const constraints = { audio: false, video: { width: _this.videoWidth, height: _this.videoHeight } } 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() // _this.$emit('cameraReady') _this.setImage() } }) .catch((err) => { alert(err) console.log(err) }) }, // 绘制图片(拍照功能) setImage() { const _this = this // 点击,canvas画图 _this.thisContext.drawImage( _this.thisVideo, 0, 0, _this.videoWidth, _this.videoHeight ) debugger // 获取图片base64链接 const image = this.thisCancas.toDataURL('image/png') // this.$emit('captured', image) this.handleFaceCaptured(image) }, handleFaceCaptured(image) { console.log(image) this.faceList.push(image) console.log(this.faceList.length) if (this.tryFaceLogin === false) { return '' } if (this.tryCount < 5) { // 如果拍到照片,调用接口进行登录,同时停止拍照 if (this.faceList.length > this.tryCount) { faceLogin({ image: this.faceList[this.tryCount] // 取一张图进行尝试 }).then(response => { console.log(response) if (response.code === 200) { if (response.success === true) { // 设置token const data = response.data setToken(data.token) this.$store.commit('SET_TOKEN', data.token) // 关闭摄像头 this.stopNavigator() // 跳转页面 this.$message.success('登录成功') this.$router.push({ path: '/' }) } else { // 登录失败,重新触发拍照并识别 if (response.message === '') { response.message = '人脸匹配失败' } this.$message.warning(response.message + ',已尝试' + this.tryCount + '次') const that = this setTimeout(function() { that.setImage() }, 1000) } } }) this.tryCount++ } } else { this.$message.error('人脸登录失败,请重试或联系管理员') // this.$router.push('/applogin') } }, // 关闭摄像头 stopNavigator() { if (this.thisVideo != null && this.thisVideo.srcObject !== null) { this.thisVideo.srcObject.getTracks()[0].stop() } } } } </script> <style lang="scss" scoped> .camera_outer { width: 100%; height: 100%; overflow: hidden; background-size: 100%; } </style>