在h5页面中调用摄像头实现扫描二维码功能

生产环境必须是https
<div id="app">
    <div class="scannow" @click="openScan">扫一扫</div>
    <div class="scanMask" v-show="showMask">
        <div class="scanvideo" v-show="showVideo">
            <video
                id="videoEle"
                ref="videoEle"
                width="300"
                height="300"
                playsinline
                autoplay
                x5-video-player-type="h5"
                style='object-fit:fill'
            ></video>
        </div>
        <div class="scancanvas" v-show="!showVideo">
            <canvas width="300" height="300" id="canvasEle" ref="canvasElement"></canvas>
        </div>
    </div>
</div>
import jsQR from 'jsqr'
data(){
    return{
      canvas2d: undefined,
      outputData:null,
      showVideo: true,
      showMask: false,
    }
},
destroyed (){
    this.closeCamera()
},
主要方法:
methods:{
        //调摄像头
        openScan(){
            this.showMask = true
            //Toast("摄像头启动中...")
            if (navigator.mediaDevices === undefined) {
                navigator.mediaDevices = {};
            }
            if (navigator.mediaDevices.getUserMedia === undefined) {
                navigator.mediaDevices.getUserMedia = function (constraints) {
                    var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia;
                    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 (window.stream) {
                window.stream.getTracks().forEach(track => {
                    track.stop();
                });
            }
            var constraints = window.constraints = {
                audio: false,
                video: {
                    sourceId: 'default',
                    facingMode:  { exact: "environment" }
                }
            };
            navigator.mediaDevices.getUserMedia(constraints).then(stream=>{
              var video = document.getElementById('videoEle');
              // 旧的浏览器可能没有srcObject
              if ("srcObject" in video) {
                video.srcObject = stream;
              } else {
                // 防止在新的浏览器里使用它,应为它已经不再支持了
                video.src = window.URL.createObjectURL(stream);
              }
              video.onloadedmetadata = function() {
                video.play();
              };
              requestAnimationFrame(this.tick)
            }).catch(err=>{
              console.log(err)
              //Toast(err)
            })
        },
        tick(){
          if( this.$refs.videoEle.readyState === this.$refs.videoEle.HAVE_ENOUGH_DATA ) {
            //this.canvasHeight = this.$refs.videoEle.videoHeight
            //this.canvasWidth = this.$refs.videoEle.videoWidth
            !this.canvas2d && (this.canvas2d = this.$refs.canvasElement.getContext('2d'))
            this.canvas2d.drawImage(this.$refs.videoEle, 0, 0, 300, 300)
            var imageData = this.canvas2d.getImageData(0, 0, 300, 300)
            var code = jsQR(imageData.data, imageData.width, imageData.height, {
              inversionAttempts: 'dontInvert'
            })
            if (code) {
              this.drawLine(code.location.topLeftCorner, code.location.topRightCorner, '#FF3B58')
              this.drawLine(code.location.topRightCorner, code.location.bottomRightCorner, '#FF3B58')
              this.drawLine(code.location.bottomRightCorner, code.location.bottomLeftCorner, '#FF3B58')
              this.drawLine(code.location.bottomLeftCorner, code.location.topLeftCorner, '#FF3B58')
              this.outputData = code.data
              this.closeCamera()
              return false
            } else {
              this.outputData = null
            }
          }
          requestAnimationFrame(this.tick)
        },
        //绘制canvas
        drawLine (begin, end, color) {
          this.canvas2d.beginPath()
          this.canvas2d.moveTo(begin.x, begin.y)
          this.canvas2d.lineTo(end.x, end.y)
          this.canvas2d.lineWidth = 4
          this.canvas2d.strokeStyle = color
          this.canvas2d.stroke()
        },
        closeCamera(){
            this.showVideo=false
            if (this.$refs.videoEle.srcObject) {
                this.$refs.videoEle.srcObject.getTracks().forEach(function (track) {
                    track.stop()
                })
                this.$refs['videoEle'].srcObject = null
            }
            //this.showMask = false
        }
}

liuxk
91 声望0 粉丝

引用和评论

0 条评论