vue2调用摄像头拍照并识别二维码

发布时间 2023-06-20 15:36:44作者: jqynr
参考:
https://blog.csdn.net/qq_33270001/article/details/124632110
https://www.cnblogs.com/skylineStar/p/16149694.html
图像解二维码:qrcode-decoder
摄像头需要在本地和ssl环境下运行
因为qrcode-decoder 组件中引用一直在报错,所以只能放到全局index.html,外部引用了
 
index.html
<!DOCTYPE html>
<html lang="">

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <link rel="icon" href="<%= BASE_URL %>favicon.ico">
  <title>
    <%= htmlWebpackPlugin.options.title %>
  </title>
  <script src="https://unpkg.com/qrcode-decoder@0.3.1/dist/index.min.js"></script>

</head>

<body>
  <noscript>
    <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
        Please enable it to continue.</strong>
  </noscript>
  <div id="app"></div>
  <!-- built files will be auto injected -->
  <script>
    var qr = new QrcodeDecoder();</script>
</body>

</html>

 

 
HelloWorld.vue
<template>
  <div class="hello">
    <div class="video-container">
      <video ref="cameraVideo"></video>
      <canvas ref="cameraCanvas" width="500" height="500"></canvas>
    </div>
    <div class="btns">
      <button class="btn" @click="openCamera()">开启摄像</button>
      <button class="btn" @click="stopCamera()">停止摄像</button>
      <button class="btn" @click="takePicture()">拍照</button>
      <button class="btn" @click="downPhoto()">下载</button>
    </div>
    <div>二维码地址:{{ qrurl }}</div>
  </div>
</template>

<script>
console.log(qr)
// import QrcodeDecoder from 'qrcode-decoder';
// console.log(QrcodeDecoder)
// var qr = new QrcodeDecoder();
export default {
  name: "HelloWorld",
  props: {
    msg: String,
  },
  data() {
    return {
      video: undefined,
      canvas: undefined,
      qr: undefined,
      qrurl: "",
      config: {
        // video属性设置
        video: {
          width: 500,
          height: 500,
        },
      },
    };
  },
  methods: {
    /**
     * 开启摄像
     */
    openCamera() {
      let self = this;
      navigator.mediaDevices
        .getUserMedia(self.config)
        .then((mediaStream) => {
          //接收一个mediaStream参数与video标签进行对接
          self.video.srcObject = mediaStream;
          self.video.play();
        })
        .catch((err) => {
          console.log(err);
        });
    },
    // 停止摄像
    stopCamera() {
      self.video.pause();
    },

    /**
     * 拍照、canvas绘制
     */
    takePicture() {
      let ctx = this.canvas.getContext("2d");
      ctx.drawImage(this.video, 0, 0, this.config.video.width, this.config.video.height);
      let imageData = ctx.getImageData(
        0,
        0,
        this.config.video.width,
        this.config.video.height
      );
      console.log(99, imageData);
    },

    /**
     * canvas下载图片
     */
    downPhoto() {
      const MIME_TYPE = "image/png";
      const dlLink = document.createElement("a");
      dlLink.download = "测试照片";
      dlLink.href = this.canvas.toDataURL(MIME_TYPE);
      dlLink.dataset.downloadurl = [MIME_TYPE, dlLink.download, dlLink.href].join(":");
      document.body.appendChild(dlLink);
      dlLink.click();
      document.body.removeChild(dlLink);
    },
  },
  mounted() {
    this.video = this.$refs.cameraVideo;
    this.canvas = this.$refs.cameraCanvas;
    qr.decodeFromVideo(this.video).then((res) => {
      this.qrurl = res.data;
      console.log(res, res.data);
    });
  },
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
* {
  padding: 0;
  margin: 0;
}

.btn {
  width: 100px;
  padding: 10px 0;
  border-radius: 4px;
  background: #ff5415;
  text-align: center;
  color: #fff;
  cursor: pointer;
  border: none;
  font-size: 16px;
}

video,
canvas {
  width: 500px;
  height: 500px;
  border: 1px solid #ff5415;
  border-radius: 4px;
  margin-left: 5px;
}

.camera-warpper {
  padding: 20px 0;
  width: 100%;
}

.video-container {
  display: flex;
  align-items: center;
  justify-content: center;
}

.btns {
  padding: 20px 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

button + button {
  margin-left: 10px;
}
</style>