首页 > 其他分享 >vue-qrcode-reader实现简单的实时扫一扫功能

vue-qrcode-reader实现简单的实时扫一扫功能

时间:2023-01-03 10:58:29浏览次数:65  
标签:qr scanner vue 100% 扫一扫 camera reader qrcode

1. 下载与安装插件vue-qecode-reader

  官网:https://gruhn.github.io/vue-qrcode-reader/demos/Simple.html

npm install --save vue-qecode-reader
或者 cnpm install --save vue-qrcode-reader

2.实现

1.QrcodeReader.vue

camera 有着以下属性:

  rear: 当camera为rear值的时候调用前摄像头;

  front: 当camera为front值的时候调用后摄像头;

  off: 当camera为off值的时候调用关闭摄像头,会获取最后一帧用于显示;

  auto: 是用于开始获取摄像头,也是默认属性。

torch 的属性是布尔值,当为

  true的时候打开手电筒,

  false是关闭摄像头。

 

<template>     <div class="qrcode">         <div class="code">             <div class="qrcode-drop-zone" v-show="qrcode">                 <!-- decode是扫描结果的函数,torch用于是否需要打开手电筒,init用于检查该设备是否能够调用摄像头的权限,camera可用于打开前面或者后面摄像头  -->                 <qrcode-drop-zone @decode="onDecode">                     <qrcode-stream @decode="onDecode" :torch="torchActive" @init="onInit" :camera="camera">                             <div class="qr-scanner">                                 <div class="box">                                     <div class="line"></div>                                     <div class="angle"></div>                                 </div>                             </div>                     </qrcode-stream>                 </qrcode-drop-zone>             </div>             <div class="code-button">                 <van-button type="info" @click="switchCamera" plain>相机反转</van-button>                 <!-- <van-button type="info" @click="ClickFlash" plain>打开手电筒</van-button> -->                 <van-button type="info" @click="turnCameraOff" plain>                     {{ qrcode === true ? '关闭相机' : '打开相机' }}                 </van-button>             </div>         </div>     </div> </template>
<script> // 引用vue-qrcode-reader插件 import { QrcodeStream, QrcodeDropZone } from 'vue-qrcode-reader'
export default {     name: 'Approve',     props: {         camera: {             type: String,             default: 'rear'         },         torchActive: {             type: Boolean,             default: false         },         qrcode: {             type: Boolean,             default: false         },         noStreamApiSupport: {             type: Boolean,             default: false         }     },     data () {         return { error: '' }     },     created () {},
    components: {         // 注册组件         QrcodeStream,         QrcodeDropZone         // QrcodeCapture     },     methods: {         // 扫码结果回调         onDecode (result) {             this.$emit('onDecode', result)         },         // 相机反转         switchCamera () {             this.$emit('switchCamera')         },         // 关闭、打开相机         turnCameraOff () {             this.$emit('turnCameraOff')         },         // 打开手电筒         ClickFlash () {             this.$emit('ClickFlash')         },         // 检查是否调用摄像头         onInit (promise) {             this.$emit('onInit', promise)         }     } } </script> <style lang="scss" scoped> ::v-deep {     .qrcode-stream-camera {         height: 85vh;     } } .code {     // width: 500px;     // height: 500px;     width: 100%;     height: 100%;     margin: 88px auto 0;     .qrcode-drop-zone {         width: 100%;         height: 85vh;         margin: 0 auto;           background: #000;     }     .code-button {         width: 100%;         position: fixed;         left: 0;         bottom: 10px;         display: flex;         .van-button {             flex: 1;             border: none;         }     }
    .qr-scanner {     width: 100%;     height: 85vh;       background-image:         linear-gradient(0deg,           transparent 24%,           rgba(32, 255, 77, 0.1) 25%,           rgba(32, 255, 77, 0.1) 26%,           transparent 27%,           transparent 74%,           rgba(32, 255, 77, 0.1) 75%,           rgba(32, 255, 77, 0.1) 76%,           transparent 77%,           transparent),         linear-gradient(90deg,           transparent 24%,           rgba(32, 255, 77, 0.1) 25%,           rgba(32, 255, 77, 0.1) 26%,           transparent 27%,           transparent 74%,           rgba(32, 255, 77, 0.1) 75%,           rgba(32, 255, 77, 0.1) 76%,           transparent 77%,           transparent);       background-size: 3rem 3rem;       background-position: -1rem -1rem;       position: relative;       background-color: #1110;
      /* background-color: #111; */     }
    .qr-scanner .box {       width: 100%;       height: 100%;       position: absolute;       left: 50%;       top: 50%;       transform: translate(-50%, -50%);       overflow: hidden;       /* background: url('http://resource.beige.world/imgs/gongconghao.png') no-repeat center center; */     }
    .qr-scanner .line {       height: calc(100% - 2px);       width: 100%;       background: linear-gradient(180deg, rgba(0, 255, 51, 0) 43%, #00ff33 211%);       border-bottom: 3px solid #00ff33;       transform: translateY(-100%);       animation: radar-beam 2s infinite alternate;       animation-timing-function: cubic-bezier(0.53, 0, 0.43, 0.99);       animation-delay: 1.4s;     }
    .qr-scanner .box:after,     .qr-scanner .box:before,     .qr-scanner .angle:after,     .qr-scanner .angle:before {       content: '';       display: block;       position: absolute;       width: 3vw;       height: 3vw;
      border: 0.2rem solid transparent;     }
    .qr-scanner .box:after,     .qr-scanner .box:before {       top: 0;       border-top-color: #00ff33;     }
    .qr-scanner .angle:after,     .qr-scanner .angle:before {       bottom: 0;       border-bottom-color: #00ff33;     }
    .qr-scanner .box:before,     .qr-scanner .angle:before {       left: 0;       border-left-color: #00ff33;     }
    .qr-scanner .box:after,     .qr-scanner .angle:after {       right: 0;       border-right-color: #00ff33;     }
    @keyframes radar-beam {       0% {         transform: translateY(-100%);       }
      100% {         transform: translateY(0);       }     } } </style>  

2.index.vue

<template>     <div class="qrcode">         <div class="box">             <qrcode                 :qrcode="qrcode"                 :camera="camera"                 :torchActive="torchActive"                 @switchCamera="switchCamera"                 @ClickFlash="ClickFlash"                 @turnCameraOff="turnCameraOff"                 @onDecode="onDecode"                 @onInit="onInit"             />         </div>     </div> </template> <script> export default {     data () {         return {             qrcode: true,             torchActive: false,             camera: 'front'         }     },     mounted () {},     methods: {         // 打开相机         clickCode () {             // camera:: 'rear'--前摄像头,'front'后摄像头,'off'关闭摄像头,会获取最后一帧显示,'auto'开始获取摄像头             this.qrcode = true             this.camera = 'rear'         },         // 扫码结果回调         onDecode (result) {             console.log(result)             this.turnCameraOff()         },         // 相机反转         switchCamera () {             switch (this.camera) {             case 'front':                 this.camera = 'rear'                 break             case 'rear':                 this.camera = 'front'                 break             default:                 this.$toast('错误')             }         },         // 关闭相机??????         turnCameraOff () {             // this.camera = 'off'             this.qrcode = !this.qrcode             if (this.camera === 'off') {                 this.camera = 'front'             } else {                 this.camera = 'off'             }         },         // 打开手电筒         ClickFlash () {             switch (this.torchActive) {             case true:                 this.torchActive = false                 break             case false:                 this.torchActive = true                 break             default:                 this.$toast('错误')             }         },
        // 检查是否调用摄像头         async onInit (promise) {             try {                 await promise             } catch (error) {                 if (error.name === 'StreamApiNotSupportedError') {                 } else if (error.name === 'NotAllowedError') {                     this.errorMessage = 'Hey! I need access to your camera'                 } else if (error.name === 'NotFoundError') {                     this.errorMessage = 'Do you even have a camera on your device?'                 } else if (error.name === 'NotSupportedError') {                     this.errorMessage =                         'Seems like this page is served in non-secure context (HTTPS, localhost or file://)'                 } else if (error.name === 'NotReadableError') {                     this.errorMessage = "Couldn't access your camera. Is it already in use?"                 } else if (error.name === 'OverconstrainedError') {                     this.errorMessage =                         "Constraints don't match any installed camera. Did you asked for the front camera although there is none?"                 } else {                     this.errorMessage = 'UNKNOWN ERROR: ' + error.message                 }             }         }     },     components: {         qrcode: () => import('./qrcode-reader.vue')     } } </script> <style lang="scss" scoped> .qrcode {     .box {         width: 100%;     } } </style>

3.注意点

  1. 调用的是浏览器的摄像头

  2. 该插件只适用于扫描二维码,而不适用于扫描条形码。

  3. vue-qrcode-reader这个插件只适用于本地调试或者带有https的域名,http是不能用这个插件的。具体原因请查看官方文档

标签:qr,scanner,vue,100%,扫一扫,camera,reader,qrcode
From: https://www.cnblogs.com/chunying/p/17021411.html

相关文章

  • antd vue3 图片 手动上传
    <template><a-uploadv-model:file-list="fileList"name="avatar"list-type="picture-card"class="avatar-uploader":show-upload-list="false......
  • vue3和vue2对比
    compostionapi:组合api/注入api(3合成型apiCompositionAPI|2选项型apiOptionsAPI)双向数据绑定、响应式原理api的改变this在vue3中与vue2中代表着完成不一样的东西......
  • vue学习
    vue3中ref函数和reactive函数1、ref函数作用:定义一个响应式的数据语法:constxx=ref(initValue)创建一个包含响应式数据的引用对象(reference对象,简称ref对象)js中......
  • Vue拖动指令
    drag.jsimport_from"lodash";classDrap{constructor(el,option={parent:null}){this.el=el;this.x=0;this.y=0;this.el.sty......
  • vue-slot及自定义分发
    Vue-slot插槽应用在组合组件的场景中<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title></head><body><divid="app">......
  • 2023.01.03 - vue项目开启https调试
    vue-cli3.x项目:使用vue脚手架3.x搭建的项目,配置开启https方法比较简单,在项目根目录下的vue.config.js文件中增加属性https:true即可。//vue.config.jsmodule.expor......
  • 前端二面vue面试题(边面边更)
    Vuex有哪几种属性?有五种,分别是State、Getter、Mutation、Action、Modulestate=>基本数据(数据源存放地)getters=>从基本数据派生出来的数据mutations=>提交......
  • 滴滴前端一面高频vue面试题及答案
    keep-alive使用场景和原理keep-alive是Vue内置的一个组件,可以实现组件缓存,当组件切换时不会对当前组件进行卸载。一般结合路由和动态组件一起使用,用于缓存组件......
  • vue组件通信6种方式总结(常问知识点)
    前言在Vue组件库开发过程中,Vue组件之间的通信一直是一个重要的话题,虽然官方推出的Vuex状态管理方案可以很好的解决组件之间的通信问题,但是在组件库内部使用Vuex往往会......
  • Vue3:子组件 watch 父组件传递的 props,watch 不触发,该如何通知子组件更新?
    问题阐述问题描述父组件传递给子组件props,由于父组件的业务需求,希望子组件通过watch监听props修改数据。父组件模板:<PaginationPageref="pagination"@fixed......