我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第1篇文章,点击查看活动详情
公司有线上电子签约,其中有活体检测(人脸识别)的功能,我自己封装了一个活体检测录屏小工具,主要是用于h5端。下面我就详细讲解这个小工具的封装过程。
我先说一下活体检测的流程,进入活体检测页面,首先会出现四个随机数字,然后提示用户记住这四个数字,点击活体检测按钮进入录制视频页面,录制视频的过程中,用户念出刚才的四个数字,录制视频完成后,会把录制的视频发送给后端,进行活体检测认证,这就是活体检测的过程。
那录制视频是怎么实现的呢,上文有提到点击活体检测按钮进入录制视频页面,其中点击活体检测按钮触发的事件代码如下:
creatInput() {
let btnWrap = document.getElementsByClassName('btn-wrap')[0];
if(document.getElementById('video')) return;
let inputElement = document.createElement('input');
inputElement.setAttribute('id','video');
inputElement.setAttribute('type','file');
inputElement.setAttribute('capture','user');
inputElement.setAttribute('accept','video/*');
inputElement.classList.add('input');
inputElement.style.opacity = 0;
inputElement.style.position= 'absolute';
inputElement.style.top = 0;
inputElement.style.left = 0;
inputElement.style.width = '100%';
inputElement.style.height = '100%';
inputElement.onchange = this.uploadVideo;
inputElement.onclick = this.inputClick;
btnWrap ? btnWrap.appendChild(inputElement):'';
document.getElementById('vide0').click();
}
clear() {
let video = document.getElementById('video');
video && video.remove();
}
inputClick() {
console.log('开始点击');
}
uploadVideo(data) {
let file = data.target.files[0];
this.fileVideo(file);
this.clear();
}
fileVideo(file) {
if(file.size/(1024*1024) > 20){
return tosta('录制文件过大,请重新录制')
}
go('count-down') // 去count-down页面 count-down页面是类似于一个倒计时页面
}
上面就是主要的实现代码。
有人可能会有疑惑,为什么这样写,是因为考虑到兼容性,安卓和ios是有差异的,如果用原生html去实现,这样就没有兼容性问题了,无论在哪个平台上都可以使用。
下面是count-down页面的实现
<template>
<div>
<svg style="transform: rotate(-90deg)" :width="breadth" :height="breadth" xmlns="http://www.w3.org/2000/svg"> <circle :r="(breadth-radius)/2" :cy="breadth/2" :cx="breadth/2" :stroke-width="radius"
:stroke="bgColor"
fill="none"
/>
<circle ref="bar"
:r="(breadth-radius)/2" :cy="breadth/2" :cx="breadth/2" :stroke="barColor"
:stroke-width="radius"
:stroke-linecap="isRound ? 'round' : 'square'"
:stroke-dasharray="(breadth-radius)*3.14" :stroke-dashoffset="isAnimation ? (breadth-radius) * 3.14 : (breadth - radius) * 3.14 * (100 - progress) / 100" fill="none"
/>
</svg>
</div>
</template>
<script>
export default {
props: {
breadth: [Number, String], // 圆的大小
radius: [Number, String], // 进度条厚度
progress: [Number, String], // 进度条百分比
barColor: String, // 进度条颜色
bgColor: String, // 背景颜色
isAnimation: { // 是否是动画效果
type: Boolean,
default: true,
},
isRound: { // 是否是圆形画笔
type: Boolean,
default: true,
},
id: { // 组件的id,多组件共存时使用
type: [String, Number],
default: 1,
},
duration: { // 整个动画时长
type: [String, Number],
default: 1000,
},
delay: { // 延迟多久执行
type: [String, Number],
default: 200,
},
animationFunction: { // 动画缓动函数
type: String,
default: 'cubic-bezier(0.99, 0.01, 0.22, 0.94)',
},
},
data() {
return {
idCircle: `circle_progress_keyframes_${this.id}`
}
},
beforeDestroy() {
// 清除旧组件的样式标签
document.getElementById(this.idCircle) && document.getElementById(this.idCircle).remove() },
mounted() {
if (this.isAnimation) {
// 重复定义判断
if (document.getElementById(this.idCircle)) { console.warn('vue-circle-progress should not have same id style')
document.getElementById(this.idCircle).remove() }
// 生成动画样式文件
let style = document.createElement('style')
style.id = this.idCircle
style.type = 'text/css'
style.innerHTML = `
@keyframes circle_progress_keyframes_name_${this.id} {
from {stroke-dashoffset: ${(this.width - this.radius) * 3.14}px;}
to {stroke-dashoffset: ${(this.width - this.radius) * 3.14 * (100 - this.progress) / 100}px;}}
.circle_progress_bar${this.id} {animation: circle_progress_keyframes_name_${this.id} ${this.duration}ms ${this.delay}ms ${this.animationFunction} forwards;}`
// 添加新样式文件
document.getElementsByTagName('head')[0].appendChild(style)
// 往svg元素中添加动画class
this.$refs.bar.classList.add(`circle_progress_bar${this.id}`)
}
},
}
</script>