Vue@zxing/library插件H5扫码功能

文章描述:

Vue@zxing/library插件H5扫码功能

template

<template>
  <div class="page bgc-f4f4f4">
    <div class="video-show" />
    <video id="video" ref="video" class="video vjs-fluid" autoplay />
    <span class="change" @click="change">
      <i class="el-icon-refresh" />
    </span>
  </div>
</template>

script

索引为0的是前置摄像头,索引为1的是后置摄像头,只需要调整这个索引,也就是调整上面js代码里的num就可以达到前后摄像头切换的功能

// 看到这个没,这个是一个小插件,能在手机上打开控制台,你打印的控制台信息和报错都能在这显示,具体方法自己百度
// import Vconsole from "vconsole";
import { BrowserMultiFormatReader } from "@zxing/library";
export default {
  name: "QrCodeSearch",
  components: {},
  data() {
    return {
      loadingShow: false,
      // 这个就是从@zxing/library导出来的方法,new一个实例
      codeReader: new BrowserMultiFormatReader(),
      // 这个,用来储存扫码得到的结果
      textContent: null,
      // 这个,就是当前调用的摄像头的索引,为什么是6,我会在后面说的
      num: 6,
      // 这个就是扫描到的摄像头的数量
      videoLength: ""
    };
  },
  created() {
    // const vconsole = new Vconsole();
    // vconsole;
    // 让我们调用这个方法尝试打开摄像头
    this.openScan();
  },
  methods: {
    // 开打开打
    async openScan() {
      const that = this;
      // 这个就是data里的哪个new出来的玩意,调用里面的方法
      that.codeReader
        .getVideoInputDevices()
        .then(videoInputDevices => {
          // 记录一下扫描到的摄像头数量,这个videoInputDevices是个数组,里面有扫描到的摄像头数据
          this.videoLength = videoInputDevices.length;
          // 这步我们来决定一下调用第几个摄像头,看到这个num没,这就是data里的
          const firstDeviceId = videoInputDevices[that.num].deviceId;
          // 这调用另一个方法
          that.decodeFromInputVideoFunc(
            firstDeviceId,
            videoInputDevices.length
          );
        })
        // 失败回调,为什么这里的失败回调这么写,后面会说的
        .catch(err => {
          this.num = 1;
          that.openScan();
          console.error(err);
        });
    },
    //这就是在openScan里调的另一个方法,传入想调用的摄像头id和摄像头数量
    decodeFromInputVideoFunc(firstDeviceId, length) {
      const that = this;
      that.codeReader.reset(); // 重置
      that.textContent = null; // 重置
      // 看不懂不重要,打印出来自己琢磨琢磨
      that.codeReader.decodeFromInputVideoDeviceContinuously(
        firstDeviceId,
        "video",
        (result, err) => {
          that.textContent = null;
          // 扫描成功 这个result就是扫描结果,长啥样自己打印出来看看
          if (result) {
            that.textContent = result;
            // 这里写你要对扫描结果做什么,我这里扫描出来的是个网址,写的页面跳转
            if (that.textContent) {
              setTimeout(() => {
                // window.location.href = that.textContent;
				alert(that.textContent);
                // 记得重置,不然在微信里用会有问题
                that.textContent = null;
                that.codeReader && that.codeReader.reset();
              }, 100);
            }
          }
          // 扫描失败,我这里是直接找下一个摄像头,其实可以不写
          if (err && !err) {
            this.num++;
            setTimeout(() => {
              that.tipShow = false;
            }, 2000);
            if (this.num <= length) {
              that.openScan();
            }
            console.error(err);
          }
        }
      );
    },
    // 点击切换前后摄像头
    change() {
      const that = this;
      if (this.videoLength > 2) {
        if (this.num < 2) {
          this.num = 6;
        } else {
          this.num = 1;
        }
        that.textContent = null;
        that.codeReader && that.codeReader.reset();
        that.openScan();
      } else {
        if (that.num === 0) {
          that.num = 1;
        } else {
          that.num = 0;
        }
        that.textContent = null;
        that.codeReader && that.codeReader.reset();
        that.openScan();
      }
    }
  }
}

style

<style scoped>
.video {
  width: 100vw;
  height: 100vh;
  z-index: 1;
}
.video-show {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 70vw;
  height: 70vw;
  z-index: 2;
  background: linear-gradient(to left, #fff, #fff) left top no-repeat,
    linear-gradient(to bottom, #fff, #fff) left top no-repeat,
    linear-gradient(to left, #fff, #fff) right top no-repeat,
    linear-gradient(to bottom, #fff, #fff) right top no-repeat,
    linear-gradient(to left, #fff, #fff) left bottom no-repeat,
    linear-gradient(to bottom, #fff, #fff) left bottom no-repeat,
    linear-gradient(to left, #fff, #fff) right bottom no-repeat,
    linear-gradient(to left, #fff, #fff) right bottom no-repeat;
  background-size: 2px 20px, 20px 2px, 2px 20px, 20px 2px;
}
.tip {
  width: 10vw;
  height: 10vw;
  background-color: rgb(45, 236, 45);
  border: 1px solid #ffffff;
  border-radius: 50%;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 10;
}

.bgc-f4f4f4 {
  background-color: #363636;
}

.page {
  position: relative;
  overflow-y: auto;
  position: relative;
  height: 100vh;
}
.change {
  z-index: 100;
  position: fixed;
  bottom: 40px;
  left: 50%;
  transform: translateX(-50%);
  color: #fff;
  text-align: center;
  background-color: #fff;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  line-height: 60px;
  /* align-content: center; */
}
.el-icon-refresh {
  color: #000;
  font-size: 25px;
}
</style>

 

发布时间:2023/01/05

发表评论