vue扫码二维码
vue实现二维码识别有些好的组件?
-
vue3-qr-reader
HJ29/vue3-qr-reader (github.com)
这是一个适用于vue3的扫码插件, 有很高的自定义度, 用法也很简便, 下面是我根据github案例改写的封装组件, 引入组件后在父组件监听子组件的
ok事件获取扫码结果:// ScanPage.vue <template> <!-- 适用于vue3的扫码组件 --> <div class="w-full md:w-80 h-auto overflow-hidden rounded-lg mx-auto my-10"> <qr-stream :camera="camera" :torch="flashActive" @decode="onDecode" @init="onInit" > <div v-if="error" class="text-red-400 text-center"></div> </qr-stream> </div> </template> <script> import { QrStream } from 'vue3-qr-reader' export default { components: { QrStream }, props: { scancode: { type: Boolean, default: false } }, data() { return { result: null, camera: 'auto', error: '', flash: false, flashActive: false } }, watch: { scancode(newValue) { if (newValue) { this.turnCameraOn() } else { this.turnCameraOff() } } }, methods: { // 扫码结果回调 onDecode(data) { this.result = data console.log(this.result) // 停止扫码 this.turnCameraOff() // 延时1s后开启扫码 if (this.result !== '') { // 在父组件监听 ok 事件获取扫码结果 this.$emit('ok', this.result) } setTimeout(() => { this.turnCameraOn() }, 1000) }, // 关闭扫码 turnCameraOff() { this.camera = 'off' }, // 开始扫码 turnCameraOn() { this.camera = 'auto' this.result = null }, // 初始化 async onInit(promise) { try { const { capabilities } = await promise this.flash = capabilities.torch } catch (error) { if (error.name === 'NotAllowedError') { this.error = 'ERROR: you need to grant camera access permisson' } else if (error.name === 'NotFoundError') { this.error = 'ERROR: no camera on this device. Try upload option.' } else if (error.name === 'NotSupportedError') { this.error = 'ERROR: secure context required (HTTPS, localhost)' } else if (error.name === 'NotReadableError') { this.error = 'ERROR: is the camera already in use?' } else if (error.name === 'OverconstrainedError') { this.error = 'ERROR: installed cameras are not suitable' } else if (error.name === 'StreamApiNotSupportedError') { this.error = 'ERROR: Stream API is not supported in this browser' } } } } } </script> <style scope> @tailwind base; @tailwind components; @tailwind utilities; body { @apply bg-gray-100 overflow-x-hidden; } .container { @apply w-4/5 md:max-w-6xl mx-auto; } a.router-link-active { @apply text-indigo-500; } a.logo { @apply text-gray-800; } .nav { @apply px-3 md:px-0 w-full md:max-w-6xl mx-auto; } /* Transition */ .slide-enter-active { transition: all 0.3s ease-out; } .slide-leave-active { transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1); } .slide-enter-from, .slide-leave-to { transform: translateX(20px); opacity: 0; } .fade-enter-active, .fade-leave-active { transition: opacity 0.5s ease; } .fade-enter-from, .fade-leave-to { opacity: 0; } </style> -
vue-qrcode-reader
gruhn/vue-qrcode-reader:一组 Vue.js 组件,用于检测和解码 QR 码。 (github.com)
适用于vue2的扫码组件, 不支持深色二维码. 下面是我根据github案例改写的封装组件, 引入组件后在父组件监听子组件的
ok事件获取扫码结果, 通过prop(scancode)控制是否开启扫码:// scan.vue 组件 <template> <!-- 适用于vue2的扫码组件但不支持深色二维码 --> <div v-if="scancode" class="scan"> <qrcode-stream @decode="onDecode" @init="onInit"> <div> <div class="qr-scanner"> <div class="box"> <div class="line" /> <div class="angle" /> </div> </div> </div> </qrcode-stream> </div> </template> <script> // 下载插件 // cnpm install --save vue-qrcode-reader // 引入 import { QrcodeStream } from 'vue-qrcode-reader' export default { // 注册 components: { QrcodeStream }, props: { scancode: { type: Boolean, default: false } }, data() { return { result: '', // 扫码结果信息 error: '' // 错误信息 } }, created() { this.clickCode() }, methods: { clickCode() { this.scancode = true }, // 回调扫描结果 onDecode(result) { if (result !== '') { this.scancode = false this.$emit('ok', result) } }, // 检查是否调用摄像头 async onInit(promise) { try { await promise } catch (error) { if (error.name === 'NotAllowedError') { this.error = 'ERROR: 您需要授予相机访问权限' } else if (error.name === 'NotFoundError') { this.error = 'ERROR: 这个设备上没有摄像头' } else if (error.name === 'NotSupportedError') { this.error = 'ERROR: 所需的安全上下文(HTTPS、本地主机)' } else if (error.name === 'NotReadableError') { this.error = 'ERROR: 相机被占用' } else if (error.name === 'OverconstrainedError') { this.error = 'ERROR: 安装摄像头不合适' } else if (error.name === 'StreamApiNotSupportedError') { this.error = 'ERROR: 此浏览器不支持流API' } } } } } </script> <style scoped> .error { font-weight: bold; color: red; } </style> <style lang="scss" scoped> @import "@/styles/scancode.scss"; </style>// scancode.scss $barwidth:20vw; $barheight:20vw; .scan{ // width: 30vw; width: $barwidth - 0.3 ; height: $barheight - 0.3 ; //TODO 如过需要在position:fixed下居中显示则需要解开下面四条注释 // z-index: 1000; border-color: #585858; // position: fixed; // top: calc(50% - 20vh); // left: calc(50% - 10vw); } .qrcode-stream-camera{ width: 100%; height: 100%; display: block; -o-object-fit: cover; object-fit: cover; position: absolute; top: 50%; left: 50%; } .qr-scanner { 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; width: 100%; /* height: 100%; */ //TODO 如过需要在position:fixed下居中显示则需要解开下面两条注释 // height: 100vh; // position: relative; background-color: #1110; /* background-color: #111; */ } .qr-scanner .box { width: $barwidth; height: $barheight; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); overflow: hidden; border: 0.1rem solid rgba(0, 255, 51, 0.2); /* 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); } } -
vue-qr-reader
vue-qr-reader (pulilab.github.io)
适用于vue2的扫码插件, 支持深色, 但自定义程度低
直接在组件中使用:
<template> <vue-qr-reader v-if="scancode" ref="qr" class="qrcode" @code-scanned="codeArrived" /> </template> <script> // 安装: npm install -s vue-qr-reader import VueQrReader from 'vue-qr-reader/dist/lib/vue-qr-reader.umd.js' export default { components: { VueQrReader }, data(){ return { // 通过更改scancode的值开控制扫码组件是否显示 scancode: false } } methods:{ // 返回扫描结果并关闭摄像头 codeArrived(result) { if (result !== '') { this.scancode = false this.$message({ type: 'success', message: result }) }, } } </script>