vue3 添加读卡器身份证设备和拍照

 首先安装读卡器驱动

去官网下载安装包服务下载_华视电子

原文连接:

http://t.csdnimg.cn/YoSu2icon-default.png?t=O83Ahttp://t.csdnimg.cn/YoSu2

新建reader.js文件

 3.js文件引入vue中,调用readIdCard方法读取身份证信息

const fileList = reactive({
  // 文件ID
  idCard: '',
  // 文件名称
  nameCard: '',
  // base64
  base64Card: '',
})


// 链接身份证读卡器
const connectCard = () => {
  const loading = ElLoading.service({
    lock: true,
    text: '正在链接设备,请稍后',
    background: 'rgba(0, 0, 0, 0.7)'
  })
  // 链接读卡器
  openDevice((res: IConnectRes) => {
    if (res.resultFlag === 0) {
      loading.close()
      readCardInfo()
    } else {
      loading.close()
      ElMessage({
        showClose: true,
        message: '无法连接到身份证设备!',
        type: 'error'
      })
    }
  })
}

//读取身份证
const readCardInfo = () => {
  const loading = ElLoading.service({
    lock: true,
    text: '正在读取,请稍后',
    background: 'rgba(0, 0, 0, 0.7)'
  })
  readIdCard((res: ICardInfo) => {
    if (res.resultFlag === 0) {
      loading.close()
      fileList.idCard= res.certNumber
      fileList.nameCard= res.partyName
      fileList.base64Card= res.identityPic
    } else {
      loading.close()
      ElMessage({
        showClose: true,
        message: '身份证读取失败,重新读取!',
        type: 'error'
      })
    }
  })
}

4.调用电脑的摄像头 拍照

原文连接:

http://t.csdnimg.cn/5w4ZSicon-default.png?t=O83Ahttp://t.csdnimg.cn/5w4ZS

<template>
  <Dialog
    :title="`拍照`"
    v-model="dialogVisible"
    @dialog-open="dialogShow()"
    :width="'840px'"
    :max-height="606"
    id="loading"
  >
    <div>
      <video id="video" v-show="!state.isCanvas" class="w-100% h-600px"></video>
      <canvas id="canvas" class="display-none w-100%"></canvas>
    </div>
    <div class="output" v-show="state.isCanvas">
      <img id="photo" class="w-100% h-600px block" />
    </div>
    <template #footer>
      <ElButton size="large" @click="close()" class="user-lg-size">取消</ElButton>
      <ElButton size="large" @click="takePhone()" type="primary" class="user-lg-size"
        >拍照并保存</ElButton
      >
    </template>
  </Dialog>
</template>
<script setup lang="ts">
import { Dialog } from '../../Dialog'
import { ref, reactive, nextTick, onMounted } from 'vue'
import { ElLoading, ElMessage, ElButton } from 'element-plus'
import { videoList } from './types'

const emit = defineEmits(['get-photo'])
const dialogVisible = ref(false)
//摄像头相关
const state = reactive({
  imgSrc: '',
  blobFile: '',
  preViewVisible: false,
  isCanvas: false,
  dataurl: undefined,
  loadingInstance: false
})
const video = ref()
const canvas = ref()
const ctx = ref()
const streaming = ref(false)
const photo = ref()
const cameraId: any = ref()
const loading = ref()
//将截图缩放到指定宽度
const width = 2500
let height = 0
//获取摄像头列表
const videoArr = reactive<videoList>({
  list: [] as any
})
// 弹框显示
const show = () => {
  // 显示弹框
  dialogVisible.value = true
}

const dialogShow = () => {
  // 显示相机画面
  state.isCanvas = false
  //获取相机所需信息
  nextTick(() => {
    //获取video节点
    video.value = document.getElementById('video')
    // 获取画布节点
    canvas.value = document.getElementById('canvas')
    // 图片展示
    photo.value = document.getElementById('photo')
    // 为画布指定绘画为2d类型
    if (canvas.value) {
      ctx.value = canvas.value.getContext('2d')
    }
    //获取摄像头权限
    getCompetence()
  })
}

//关闭弹窗
const close = () => {
  dialogVisible.value = false
}

//点击拍照截图画面
const takePhone = () => {
  canvas.value.width = width
  canvas.value.height = height
  state.isCanvas = true
  ctx.value.drawImage(video.value, 0, 0, width, height)
  state.dataurl = canvas.value.toDataURL('image/jpeg')
  state.preViewVisible = true
// 这里获取到了拍照的base64
  photo.value.setAttribute('src', state.dataurl)
  emit('get-photo', state.dataurl)
  close()
}

// 调用摄像头权限
const getCompetence = async () => {
  loading.value = ElLoading.service({
    lock: true,
    text: '正在获取摄像头权限...',
    target: document.querySelector('#loading') as any
  })
  //必须在model中render后才可获取到dom节点,直接获取无法获取到model中的dom节点
  if (navigator.mediaDevices === undefined) {
    let navigator: any
    navigator.menavigatordiaDevices = {}
  }
  // 一些浏览器实现了部分mediaDevices,我们不能只分配一个对象
  // 使用getUserMedia,因为它会覆盖现有的属性。
  // 这里,如果缺少getUserMedia属性,就添加它。
  if (navigator.mediaDevices.getUserMedia === undefined) {
    navigator.mediaDevices.getUserMedia = function (constraints: any) {
      // 首先获取现存的getUserMedia(如果存在)
      let navigator: any
      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)
      })
    }
  }

  var constraints = {
    audio: false,
    video: {
      width: 2592,
      height: 1944
    }
  }

  navigator.mediaDevices
    .getUserMedia(constraints)
    .then(function () {
      // 获取摄像头设备信息
      getVideo(loading.value)
    })
    .catch(function (err) {
      ElMessage.error('打开摄像头失败请检查浏览器设置或域名是否安全!')
      setTimeout(() => {
        loading.value.close()
        close()
      }, 1000)
    })
}

// 获取摄像头设备信息
const getVideo = (loading: any) => {
  videoArr.list = []
  if (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) {
    navigator.mediaDevices.enumerateDevices().then(function (devices) {
      for (var j = 0; j < devices.length; j++) {
        if (devices[j].kind == 'videoinput') {
          videoArr.list.push({
            label: devices[j].label,
            id: devices[j].deviceId
          })
        }
      }
      let labelRight = videoArr.list.findIndex((item) => {
        return item.label.indexOf('HD USB Camera') == 0
      })
      if (labelRight != -1) {
        let labelId = videoArr.list.find((item) => {
          return item.label.indexOf('HD USB Camera') == 0
        })?.id
        cameraId.value = labelId
        if (cameraId.value) {
          //调用获取到的摄像头权限
          TakeP(loading)
        }
      } else {
        setTimeout(() => {
          close()
          loading.close()
          ElMessage.error('您未链接正确设备,请检查!')
        }, 10000)
      }
    })
  }
}

//显示摄像画面
const TakeP = (loading: any) => {
  var constraints = {
    audio: false,
    video: {
      width: 2592,
      height: 1944,
      deviceId: cameraId.value
    }
  }
  navigator.mediaDevices
    .getUserMedia(constraints)
    .then((mediaStream) => {
      video.value.srcObject = mediaStream
      video.value.play()
      setTimeout(() => {
        loading.close()
      }, 30)
    })
    .catch((err) => {
      setTimeout(() => {
        loading.close()
      }, 30)
    })
  video.value.addEventListener(
    'canplay',
    (ev) => {
      if (!streaming.value) {
        height = video.value.videoHeight / (video.value.videoWidth / width)
        if (isNaN(height)) {
          height = width / (4 / 3)
        }
        console.log('width:' + width)
        console.log('height:' + height)
        console.log('v-width:' + video.value.videoWidth)
        console.log('v-height:' + video.value.videoHeight)
        video.value.setAttribute('width', width)
        video.value.setAttribute('height', height)
        canvas.value.setAttribute('width', width)
        canvas.value.setAttribute('height', width)
        streaming.value = true
      }
    },
    false
  )
}

//重拍
const takeAgain = () => {
  loading.value = ElLoading.service({
    lock: true,
    text: '正在获取摄像头画面...',
    target: document.querySelector('#loading') as any
  })
  state.isCanvas = false
  TakeP(loading.value)
}

defineExpose({
  show,
  loading,
  takeAgain,
  close,
  TakeP
})
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值