原生JS调摄像头扫码识别

26 阅读1分钟

index.html

<canvas class="canvas" ref="canvas"></canvas>
<el-button type="primary" @click="media()">扫一扫</el-button>
<el-button @click="cancel()">取消</el-button>
```

```
import jsQR from "jsqr";
export default {
    data(){
    return {
       timer: null,
       result: null,
       isAnimation: true,
       video: Object,
       cvsele: Object,
       canvas: Object,
    },
    
    // 初始化
    mounted() {
        this.video = document.createElement("video");
        this.cvsele = this.$refs.canvas;
        this.canvas = this.cvsele.getContext("2d");
     },
    
    methods: {
    
        // 动态扫描框绘制
        draw(begin, end) {
              this.canvas.beginPath();
              this.canvas.moveTo(begin.x, begin.y);
              this.canvas.lineTo(end.x, end.y);
              this.canvas.lineWidth = 3;
              this.canvas.strokeStyle = "red";
              this.canvas.stroke();
        },
        //取消扫描
        cancel() {
              this.isAnimation = false;
              cancelAnimationFrame(this.timer);
              setTimeout(() => {
                this.cvsele.style.display = "none";
              }, 1000);
        },
            
        // 生成图片解析扫描结果下一步操作
        sweep() {
          if (this.video.readyState === this.video.HAVE_ENOUGH_DATA) {
            const { videoWidth, videoHeight } = this.video;
            this.cvsele.width = videoWidth;
            this.cvsele.height = videoHeight;
            this.canvas.drawImage(this.video, 0, 0, videoWidth, videoHeight);
            try {
              const img = this.canvas.getImageData(0, 0, videoWidth, videoHeight);
              this.imgurl = img;
              
              // 解析扫描结果
              const obj = jsQR(img.data, img.width, img.height, {
                inversionAttempts: "dontInvert",
              });
              if (obj) {
                const loc = obj.location;
                this.draw(loc.topLeftCorner, loc.topRightCorner);
                this.draw(loc.topRightCorner, loc.bottomRightCorner);
                this.draw(loc.bottomRightCorner, loc.bottomLeftCorner);
                this.draw(loc.bottomLeftCorner, loc.topLeftCorner);
                if (this.result != obj.data) {
                  this.result = obj.data;
                  // 拿到结果取消扫码
                  this.cancel();
                  setTimeout(() => {
                     // 拿到结果进行下一步动作
                    // this.changeIdCard();
                  }, 500);
                  console.info("识别结果:", obj.data);
                }
              } else {
                console.error("识别失败,请检查二维码是否正确!");
              }
            } catch (err) {
              console.error("识别失败,请检查二维码是否正确!", err);
            }
          }
          if (this.isAnimation) {
            this.timer = requestAnimationFrame(() => {
              this.sweep();
            });
          }
        },
        
        
        // 调取摄像头
        
        media() {
              this.isAnimation = true;
              this.result = null;
              this.cvsele.style.display = "block";
              navigator.getUserMedia =
                navigator.getUserMedia ||
                navigator.webkitGetUserMedia ||
                navigator.mozGetUserMedia ||
                navigator.msGetUserMedia;
              if (navigator.mediaDevices === undefined) {
                navigator.mediaDevices = {};
              }
              if (navigator.mediaDevices.getUserMedia === undefined) {
                navigator.mediaDevices.getUserMedia = function (constraints) {
                  var getUserMedia =
                    navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
                  if (!getUserMedia) {
                    return Promise.reject(
                      new Error("getUserMedia is not implemented in this browser")
                    );
                  }
                  return new Promise(function (resolve, reject) {
                    getUserMedia.call(navigator, constraints, resolve, reject);
                  });
                };
              }
        
              if (navigator.mediaDevices) {
                navigator.mediaDevices
                  .getUserMedia({
                    video: { facingMode: "environment" },
                  })
                  .then((stream) => {
                    this.video.srcObject = stream;
                    this.video.setAttribute("playsinline", true);
                    this.video.setAttribute("webkit-playsinline", true);
                    this.video.addEventListener("loadedmetadata", () => {
                      this.video.play();
                      this.sweep();
                    });
                  })
                  .catch((error) => {
                    this.cance();
                    alert("对不起:未识别到扫描设备3!");
                    console.log(error.code + ":" + error.name + "," + error.message);
                  });
              } else if (navigator.getUserMedia) {
                navigator.getUserMedia(
                  {
                    video: { facingMode: "environment" },
                  },
                  (stream) => {
                    this.video.srcObject = stream;
                    this.video.setAttribute("playsinline", true);
                    this.video.setAttribute("webkit-playsinline", true);
                    this.video.addEventListener("loadedmetadata", () => {
                      this.video.play();
                      this.sweep();
                    });
                  },
                  (error) => {
                    this.cance();
                    alert("对不起:未识别到扫描设备1!");
                    console.log(error.code + ":" + error.name + "," + error.message);
                  }
                );
              } else {
                if (
                  navigator.userAgent.toLowerCase().match(/chrome/) &&
                  location.origin.indexOf("https://") < 0
                ) {
                  console.log(
                    "获取浏览器录音功能,因安全性问题,需要在localhost 或 127.0.0.1 或 https 下才能获取权限!"
                  );
                } else {
                  this.cance();
                  alert("对不起:未识别到扫描设备2!");
                }
              }
            },
    } 
}
```