vue项目使用Vue Qrcode Reader扫描二维码、开启闪光灯功能

1,971 阅读2分钟

项目背景:内嵌至app内的vue-cli+vant2项目

需求:调用手机相机,开启闪光灯、扫描二维码功能

所使用插件/文档:点击: [Vue Qrcode Reader](Decode by Upload | Vue Qrcode Reader (gruhn.github.io))

注意:因为安全原因相机只有在本地http://localhost 或者 https协议下才可以调用,http协议是调不起来。

该插件目前暂不支持条形码,如果你看到这篇文章时,已经支持,记得回来踢我

如何使用

1、下载插件

npm i vue-qrcode-reader

2、引入页面
<qrcode-stream @decode="onDecode" @init="onInit" :torch="torchActive" class="qrcode_stream">

</qrcode-stream>

<qrcode-capture @decode="onDecode" :capture="false" id="ischange" /> 

import { QrcodeStream, QrcodeCapture } from 'vue-qrcode-reader'

QrcodeStream 直接调用相机实时扫描二维码

@decode 拿到扫描结果的回调

@init 初始化摄像流,主要检验当前设备是否支持相机功能

torch 控制闪光灯的开/关

QrcodeCapture 选择设备本地的图片进行二维码扫描或者拍照进行扫描

capture 'environment'/后置摄像头 'user'/前置摄像头 false/选择文件

我在项目中使用时,无法进行拍照扫描,拍照扫描没有任何返回结果或者报错,不知道到咋回事

我在项目中的使用

<template>
    <div>
      <div class="sancer_cls">
        <qrcode-stream :camera="camera" @decode="onDecode" @init="onInit" :torch="torchActive" class="qrcode_stream">
          <div class="header">
            <img @click="goback" src="@/assets/imgs/back-black.png" alt="">
          </div>
          
          <p class="sancer_msg"> {{ error }} </p>

          <van-overlay :show="toLoading"/>
          <van-loading v-show="toLoading" class="loading_bg" color="#303030" size="24px"/>
          
          <img src="@/assets/imgs/QR_frame.png" class="scan_frame" alt="扫码框">
  
          <div class="stream_btn">
            <div class="btn_content" @click="importNumber">
              <img src="@/assets/imgs/importNum.png" class="btn_img" alt="输入编码"/>
              <p class="content_p">输入编码</p>
            </div>
  
            <div class="btn_content" @click="torchActiveChange">
              <img src="@/assets/imgs/switchLight.png" class="btn_img" alt="轻触照亮"/> 
              <p class="content_p">轻触照亮</p>
            </div>
  
                <div class="btn_content" @click="changeI">// 为了支持拍照扫码与使用本地图片扫码功能
              <qrcode-capture @decode="onDecode" :capture="selected" id="ischange" style="display:none"/> 
              <img src="@/assets/imgs/changeImg.png" class="btn_img" alt="选择图片"/> 
              <p class="content_p">选择图片</p>
            </div>
          </div> 
          <button v-if="showRegainCamera" @click="regainCamera" class="regain_camera">重新获取摄像头权限</button>
        </qrcode-stream>
      </div>
    </div>
  </template>
  
  <script>
  import { QrcodeStream, QrcodeCapture } from 'vue-qrcode-reader'
  export default {
    components: { 
      QrcodeStream,
      QrcodeCapture,
    },
    data () {
      return {
        result: '',
        error: '',
        torchActive: false,
        selected: false,  // 值:'environment'/后置摄像头 'user'/前置摄像头 false/选择文件
        toLoading: false, // 
        camera: 'auto', // 原本有缓存导致不能连续扫描同一个二维码,当更改摄影机道具时,此缓存将重置。可以利用这一点连续多次扫描相同的二维码。
        showRegainCamera: false,  // 重新获取摄像头权限按钮展示控制
      }
    },
    watch:{ },
    created(){ },
    mounted(){ },
    methods: {
      async onInit(promise) {  // 每次修改 camera 的值 都会重新获取一个新的摄像机流,因此会再次触发 onInit 事件
        try {
          let r = await promise
          console.log(r,'initpromise');
        } catch (error) {
          if (error.name === 'NotAllowedError') {
            this.error = "您需要授予相机访问权限"
            this.showRegainCamera = true
          } else if (error.name === 'NotFoundError') {
            this.error = "这个设备上没有摄像头"
          } else if (error.name === 'NotSupportedError') {
            this.error = "所需的安全上下文(HTTPS、本地主机)"
          } else if (error.name === 'NotReadableError') {
            this.error = "相机被占用"
          } else if (error.name === 'OverconstrainedError') {
            this.error = "摄像头不适用"
          } else if (error.name === 'StreamApiNotSupportedError') {
            this.error = " 不支持流API"
          } else if (error.name === 'InsecureContextError') {
            this.error = `请使用HTTPS或localhost使用摄像头`;
          } else {
            // this.error = `ERROR: Camera error (${error.name})`;
            this.showRegainCamera = false
          }
        } finally {
        }
      },

      async onDecode(res) {  // 拿到扫描结果
        console.log(res,'------扫描结果');
        let self = this
        // 自己项目的业务逻辑

        this.pause()
        await this.timeout(500)
        this.unpause()
      },

      async regainCamera(){ // 重新获取摄像头权限,修改了camera的值会重新出发init
        console.log('重新获取摄像头权限');
        this.pause()
        await this.timeout(500)
        this.unpause()
        // console.log(this.camera,'==cameracamer');
      },
      
      async torchActiveChange(){  // 开/关闪光灯
        let self = this
        self.torchActive = !self.torchActive
        this.pause()
        await this.timeout(500)
        this.unpause()
      },

      changeI(){  // 选择图片,触发扫码组件的方法
        console.log('选择图片,changeImg');
        document.getElementById('ischange').click()
      },
      
      unpause () {  // 控制摄像流的切换
        this.camera = 'auto'
      },

      pause () {  // 控制摄像流的切换
        this.camera = 'off'
      },

      timeout (ms) {  // 控制摄像流的切换
        return new Promise(resolve => {
          window.setTimeout(resolve, ms)
        })
      },
    }
  }
  </script>

因为安全原因相机只有在本地http://localhost 环境 或者 https环境才可以调用,http是调用不起来。

大家测试的时候记得看一下自己的环境对不对

功能测试方式

1、更改本地运行协议为https方法

vue-clli项目,在vue.config.js中配置

// 使用webpack搭建的项目如何配置暂不知,有知道的小伙伴可以评论一下哦~
devServer:{
    https:true
}

再次运行项目即可

2、在手机上运行本地项目

image.png

项目运行起来之后如果电脑有相机功能应该可以直接测试(我没用过,但是应该可以)

如果电脑不行,使用手机,项目运行起来之后如上图,会有两个本地项目地址,在手机上输入第二个地址即可测试

达成 支持摄像&只能在本地或者https协议下调用 的条件

手机上测试可以装vconsole来查看控制台

——————————————————总结的分割线———————————————————

Vue Qrcode Reader插件总体就这些了,除了拍照扫描二维码没有满足需求,其他都没问题。

拍照扫描二维码的场景其实很少,跟产品商量看可不可以直接砍掉(●ˇ∀ˇ●)

另外在ios上并没有使用过,可能有无法预见的错误,大家可以参考官方文档来进行使用

点击: [Vue Qrcode Reader](Decode by Upload | Vue Qrcode Reader (gruhn.github.io))