vue扫码二维码

vue实现二维码识别有些好的组件?

  1. 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>
       
    
  2. 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);
          }
        }
    
  3. 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>