uniapp,vue3,h5端使用zxing扫描二维码,条形码

文章目录

  • 前言
  • 一、引入zxing
    • npm
    • 直接使用js文件
  • 二、功能实现
    • 1. 获取摄像头
    • 2.开始扫描
  • 完整代码


前言

废话不多说,使用uniapp时scan方法不支持h5端,因此h5端需要自己引入三方库,我这里用的是zxing
完整代码在最后


一、引入zxing

这里有两种方法,npm和直接使用js文件,按需使用

npm

pnpm add @zxing/library
import { BrowserMultiFormatReader } from '@zxing/library'

直接使用js文件

js地址:https://unpkg.com/@zxing/library@latest/umd/index.min.js

import { BrowserMultiFormatReader } from '@/utils/zxing.js'

二、功能实现

直接使用zxing提供的方法就行,默认参数就够用,如果需要自定义,比如修改视频流清晰度之类的可以看看文档

1. 获取摄像头

// 这里的处理是因为uniapp会对video标签进行二次封装,vue的话直接用ref获取dom就行
  var video = document.getElementById('video_nav_id').getElementsByTagName('video')[0]
  video.setAttribute('id', 'video_id')
  video.setAttribute('class', 'video_calss')
  codeReader.value = new BrowserMultiFormatReader();
  codeReader.value.listVideoInputDevices().then(res => {
    if (res.length > 0) {
      videoInputDevices.value = res
      // 这里默认选择最后一个摄像头
      deviceId.value = res[res.length - 1].deviceId
    } else {
      // 没有可用的摄像头
      // todo
    }
  }).catch(err => {
    console.error(err)
  })

2.开始扫描

try {
    codeReader.value.decodeFromVideoDevice(deviceId.value, 'video_id', (res, err) => {
      if (res) handleScanningResult(res)
    })
  } catch (err) {
    uni.showToast({ title: `初始化失败${err}`, icon: 'none' });
  }

完整代码

<template>
  <view class="camera_page">
    <view class="camera_content">
      <view class="code_close" @click="closeClick()">
        <!-- <img src="../../static/close.png"> -->
      </view>
      <view class="loop_line"></view>
      <view class="video_nav">
        <video id="video_nav_id" autoplay :controls="false"></video>
      </view>
    </view>
  </view>
</template>
<script setup>
import { onLoad } from "@dcloudio/uni-app";
import { ref } from "vue";
import { BrowserMultiFormatReader } from '@zxing/library' //npm引入
// import { BrowserMultiFormatReader } from '@/utils/zxing.js' //直接引入js文件
const codeReader = ref(null)
const deviceId = ref(null)
const videoInputDevices = ref([])
const initEvent = () => {
  // 这里的处理是因为uniapp会对video标签进行二次封装,如果是Vue的话直接获取video标签
  var video = document.getElementById('video_nav_id').getElementsByTagName('video')[0] // uniapp
  // var video = document.getElementById('video_nav_id') //Vue
  video.setAttribute('id', 'video_id')
  video.setAttribute('class', 'video_calss')
  codeReader.value = new BrowserMultiFormatReader();
  codeReader.value.listVideoInputDevices().then(res => {
    if (res.length > 0) {
      videoInputDevices.value = res
      // 这里默认选择最后一个摄像头
      deviceId.value = res[res.length - 1].deviceId
    } else {
      // 没有可用的摄像头
      // todo
    }
  }).catch(err => {
    console.error(err)
  })
  startScanning()
}
onLoad(() => {
  setTimeout(() => {
    initEvent();
  }, 3000);
});
const startScanning = () => {
  try {
    codeReader.value.decodeFromVideoDevice(deviceId.value, 'video_id', (res, err) => {
      if (res) handleScanningResult(res)
    })
  } catch (err) {
    uni.showToast({ title: `初始化失败${err}`, icon: 'none' });
  }
}
const handleScanningResult = (res) => {
  // 这里处理扫描结果
  console.log(res.text)
}
// 停止扫描
const stopScanning = () => {
  codeReader.value.reset()
}
const closeClick = () => {
  // todo
}
</script>
<style scoped lang="scss">
.camera_page {
  height: 100vh;
  width: 100vw;
}

.camera_content {
  height: 100%;
  width: 100%;
  position: relative;
}

.code_close {
  height: 50rpx;
  width: 50rpx;
  position: absolute;
  left: 30rpx;
  top: 30rpx;
  z-index: 999999;
}

.code_close>img {
  height: 100%;
  width: 100%;
  display: block;
}

.loop_line {
  height: 3px;
  width: 80%;
  background-color: aliceblue;
  border-radius: 50%;
  box-shadow: 1px -4px 25px 7px rgba(255, 255, 255, 0.5);
  position: absolute;
  left: 50%;
  top: 20%;
  transform: translateX(-50%);
  animation: myfirst 3s infinite;
  z-index: 999999;
}

@keyframes myfirst {
  from {
    top: 20%;
  }

  to {
    top: 80%;
  }
}

.video_nav {
  height: 100%;
  width: 100%;
}

#video_nav_id {
  height: 100%;
  width: 100%;
}

:deep(.uni-video-cover) {
  display: none;
}
</style>

注意事项:
摄像头权限需要https协议才能调用,也即

  1. 部署到服务器时,域名需要SSL证书,也就是域名以https开头
  2. 本地开发调试时,需要开启https并加载本地证书,这里可以看看我的另一篇笔记vue项目,uniapp项目开启https,加载本地证书

你可能感兴趣的:(uni-app)