Angular 6 + jsQR - 如何在第一次成功时捕获二维码?

标签 angular qr-code

我将 jsQR ( https://www.npmjs.com/package/jsqr ) 与我的 Angular 应用程序一起使用来解码二维码。通常我将代码从 jsQR 复制到我的应用程序中,它会立即运行。但是,jsQR 仅在我在网络摄像头区域中持有二维码时读取,当将代码移开时,不会捕获先前的结果。因此,如果成功,我想捕获第一个二维码并将其绑定(bind)到表单中以提交结果。我怎样才能正确地做到这一点?

到目前为止,这是我的代码:

ngOnInit() {
    this.getQR();
}

  getQR() {
    const video = document.createElement('video');
    const canvasElement: any = document.getElementById('canvas');
    const canvas = canvasElement.getContext('2d');
    const outputContainer = document.getElementById('output');
    const outputMessage = document.getElementById('outputMessage');
    const outputData = document.getElementById('outputData');

    function drawLine(begin, end, color) {
      canvas.beginPath();
      canvas.moveTo(begin.x, begin.y);
      canvas.lineTo(end.x, end.y);
      canvas.lineWidth = 4;
      canvas.strokeStyle = color;
      canvas.stroke();
    }

    // Use facingMode: environment to attemt to get the front camera on phones
    navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment' } }).then(function(stream) {
      video.srcObject = stream;
      // video.setAttribute('playsinline', true); // required to tell iOS safari we don't want fullscreen
      video.play();
      requestAnimationFrame(tick);
    });

    function tick() {
      if (video.readyState === video.HAVE_ENOUGH_DATA) {
        canvasElement.hidden = false;
        outputContainer.hidden = false;

        canvasElement.height = video.videoHeight;
        canvasElement.width = video.videoWidth;
        canvas.drawImage(video, 0, 0, canvasElement.width, canvasElement.height);
        const imageData = canvas.getImageData(0, 0, canvasElement.width, canvasElement.height);
        const code = jsQR(imageData.data, imageData.width, imageData.height);
        if (code) {
          drawLine(code.location.topLeftCorner, code.location.topRightCorner, '#009688');
          drawLine(code.location.topRightCorner, code.location.bottomRightCorner, '#009688');
          drawLine(code.location.bottomRightCorner, code.location.bottomLeftCorner, '#009688');
          drawLine(code.location.bottomLeftCorner, code.location.topLeftCorner, '#009688');
          outputMessage.hidden = true;
          outputData.parentElement.hidden = false;
          outputData.innerText = code.data;
        } else {
          outputMessage.hidden = false;
          outputData.parentElement.hidden = true;
        }
      }
      requestAnimationFrame(tick);
    }
  }

最佳答案

我已经将 javascript 纯代码包装到 typescript 中;这是我的模板:

<canvas id="scan-canvas"></canvas>
<div id="output">
  <div id="outputMessage">No QR code detected.</div>
  <div hidden=""><b>Data:</b> <span id="outputData">{{ qrcodeDetected }}</span></div>
</div>

这里是 TS Controller :

ngOnInit() {
    this.canvasElement = <HTMLCanvasElement> document.getElementById('scan-canvas');
    this.canvasContext = this.canvasElement.getContext('2d');
    this.outputContainer = <HTMLDivElement>document.getElementById('output');
    this.outputMessage = <HTMLDivElement>document.getElementById('outputMessage');
    this.outputData = <HTMLDivElement>document.getElementById('outputData');

    this.video = <HTMLVideoElement>document.createElement('video');

    navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment' } }).then(async (stream: MediaStream) => {
        this.video.srcObject = stream;
        this.video.setAttribute('playsinline', 'true'); // required to tell iOS safari we don't want fullscreen
        await this.video.play();
        requestAnimationFrame(this.tick.bind(this));
    });
}

drawLine(begin, end, color): void {
    this.canvasContext.beginPath();
    this.canvasContext.moveTo(begin.x, begin.y);
    this.canvasContext.lineTo(end.x, end.y);
    this.canvasContext.lineWidth = 4;
    this.canvasContext.strokeStyle = color;
    this.canvasContext.stroke();
}

tick(): void {
    if (this.video.readyState === this.video.HAVE_ENOUGH_DATA) {
        this.canvasElement.hidden = false;
        this.outputContainer.hidden = false;

        this.canvasElement.height = this.video.videoHeight;
        this.canvasElement.width = this.video.videoWidth;
        this.canvasContext.drawImage(this.video, 0, 0, this.canvasElement.width, this.canvasElement.height);
        const imageData: ImageData = this.canvasContext.getImageData(0, 0, this.canvasElement.width, this.canvasElement.height);
        const code: QRCode = jsQR(imageData.data, imageData.width, imageData.height);
        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.outputMessage.hidden = true;
            this.outputData.parentElement.hidden = false;
            this.qrcodeDetected = code.data;
        } else {
            this.outputMessage.hidden = false;
            this.outputData.parentElement.hidden = true;
        }
    }
    requestAnimationFrame(this.tick.bind(this));
}

关于Angular 6 + jsQR - 如何在第一次成功时捕获二维码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51706021/

相关文章:

javascript - Angular2 - 在 SystemJS 中导入第 3 方 javascript

angular - 未验证断点(断点已设置但尚未绑定(bind))

Android studio - 从 fragment 启动二维码扫描器

java - 使用 zxing 生成正确的二维码时出现的问题

angular - 以 Angular 7 按列显示数据

javascript - 如何在解析器 Angular 中访问 queryParams

未显示 Angular FIrebase 5 对象键。所以不能删除

java - 如何从 imageView 获取 BinaryBitmap

google-apps-script - 是否可以使用谷歌应用脚​​本扫描二维码?

android - 获得二维码验证