活体检测录屏小工具

1,917 阅读2分钟

我报名参加金石计划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>