vue 浏览器识别二维码功能 pc和手机端

前言:一定是https协议,一定是https协议,一定是https协议,识别的是二维码。条形码估计不太行(因为太小了)
1:安装 "@zxing/library": "^0.20.0",
npm install @zxing/library --save (最好别用cnpm)

yarn add @zxing/library


2:上代码  (我这是放在弹窗里面了)  openScan:初始化的方法
        先看看你们的协议是http的还是https的
        一定是https协议 
        一定是https协议
        一定是https协议
        不然摄像头会报错,原因是因为会被浏览器认为是不安全的操作  

        <button @click="scan"></button>        
        <scanIndex ref="scanIndex"></scanIndex>
        methods:{

                scan(){  
                        this.$refs.scanIndex.title= "测试";

                        this.$refs.scanIndex.dialogAddVisible = true;

                        this.$refs.scanIndex.openScan();

                },

        }        
        

<template>
  <el-dialog :class="{dialogClass:dialogWidth=='100%'}" title="提示" :visible.sync="dialogAddVisible" :width="dialogWidth" @close="resetScan">
    <span slot="title">{{ title }}</span>
    <div class="dashboard-container" style="position: relative">
      <!-- <div class="dashboard-text">name: {{ name }}</div> -->
      <!-- 提示语 -->
      <!-- <div v-show="tipShow" class="scan-tip">{{ tipMsg }}</div> -->
      <!-- 扫码区域 -->
      <video
        style="object-fit:fill;"
        ref="video"
        id="video"
        class="scan-video"
        :width="videoWidth"
        :height="videoHeight"
        autoplay
      ></video>
      <div class="qr-scanner">
        <div class="box">
          <div class="line"></div>
          <div class="angle"></div>
        </div>
      </div>
      <!-- <div >{{scanText}}</div> -->
    </div>
  </el-dialog>
</template>
<script>
import { BrowserMultiFormatReader } from "@zxing/library";
export default {
  name: "Dashboard",
  computed: {},
  props: ["title"],
  data() {
    return {
      dialogAddVisible: false,
      codeReader: null,
      scanText: "", // 扫码结果文本内容
      dialogWidth:"60%",
      videoWidth:"100%",
      videoHeight:"100%",
    };
  },
  created() {
    // 移动端
    console.log(this.IsPhone())
    if(this.IsPhone()!=null){
      this.dialogWidth="100%"
      // this.videoWidth="300"
      this.videoHeight="450"
    }else{
      this.dialogWidth="60%"
    }
     
  },
  destroyed() {
      this.resetScan();
  },
    methods: {
      IsPhone() {
        let flag = navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)

        //如果包含“Mobile”(是手机设备)则返回true
        return flag;
      },
        resetScan() { 
            // this.codeReader.hasNavigator=false;
        // console.log(this.codeReader)
        if (this.codeReader) {
          this.codeReader?.reset();
            this.codeReader = null;
         }
            
        },
    async openScan() {
      let that = this; // 初始化摄像头
      this.codeReader = new BrowserMultiFormatReader();
      this.codeReader
        .getVideoInputDevices()
        .then((videoDevices) => {
          that.$message({ type: "success", message: "正在调用摄像头..." });
          //   that.tipShow = true;
          //   console.log("get-videoDevices", videoDevices);

          // 默认获取摄像头列表里的最后一个设备id,通过几部测试机发现一般前置摄像头位于列表里的前面几位,所以一般获取最后一个的是后置摄像头
          let firstDeviceId = videoDevices[videoDevices.length - 1].deviceId;
          // 一般获取了手机的摄像头列表里不止一个,有的手机摄像头高级多层,会有变焦摄像头等情况,需要做处理
          if (videoDevices.length > 1) {
            // 一般通过判断摄像头列表项里的 label 字段,'camera2 0, facing back' 字符串含有 'back' 和 '0',大部分机型是这样,如果有些机型没有,那就还是默认获取最后一个
            firstDeviceId = videoDevices.find((el) => {
              return (
                el.label.indexOf("back") > -1 && el.label.indexOf("0") > -1
              );
            })
              ? videoDevices.find((el) => {
                  return (
                    el.label.indexOf("back") > -1 && el.label.indexOf("0") > -1
                  );
                }).deviceId
              : videoDevices[videoDevices.length - 1].deviceId;
          }
          //   console.log("get-firstDeviceId", firstDeviceId);
          this.decodeFromInputVideoFunc(firstDeviceId);
        })
        .catch((err) => {
          //   this.tipShow = false;
          // console.error(err);
          that.$message.error(err);
        });
    },
    decodeFromInputVideoFunc(firstDeviceId) {
      let that = this; // 使用摄像头扫描
      // this.codeReader.reset(); // 重置
      setTimeout(() => {
        that.$message({ type: "primary", message: "正在尝试识别..." });
      }, 1000);
      this.codeReader.decodeFromInputVideoDeviceContinuously(
        firstDeviceId,
        "video",
        (result, err) => {
          // that.$message({type:"primary",message:"正在尝试识别..."});
          //   that.tipMsg = "";
          if (result) {
            that.scanText = result.text;
            if (that.scanText) {
              //   this.tipShow = false;
              // that.$alert(that.scanText, '扫码结果', {
              //     confirmButtonText: '确定',
              //     callback: action => {
              //         // that.$destroy();
              //     }
              // });
                that.resetScan();
              that.$emit("updateForm", that.scanText);
              that.dialogAddVisible = !that.dialogAddVisible;
            }
          }
        }
      );
    },
    // clickIndexLeft(){  // 返回上一页
    //   this.$destroy();
    //   this.$router.go(-1);
    //   // window.location.href = document.referrer;
    // }
  },
};
</script>

<style lang="scss" scoped>
.dashboard {
  &-container {
    margin: 30px;
  }
  &-text {
    font-size: 30px;
    line-height: 46px;
  }
}
#video {
  //   width: 100%;
}
.dialogClass /deep/ .el-dialog__body{
  padding:0;
}
.dialogClass /deep/ .dashboard-container{
  margin: 0px;
}
.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%;
  position: absolute;
  top: 0;
  // background-color: #111;
}

.qr-scanner .box {
  width: 75%;
  height: 75%;
  max-height: 75%;
  max-width: 75%;
  position: relative;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  overflow: hidden;
  border: 0.1rem solid rgba(0, 255, 51, 0.2);
}

.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;
  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>

3:效果图
PC端
 

为啥是黑的,因为

手机端 

4:结果 result.text是识别成功后的结果 可自行更改

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值