angular - Angular 6 + jsQR - 如何在第一次成功时捕获 QR 码?
问题描述
我将 jsQR ( https://www.npmjs.com/package/jsqr ) 与我的 Angular 应用程序一起使用来解码 QR。通常我将 jsQR 中的代码复制到我的应用程序中,它会立即运行。但是,jsQR 仅在我将 QR 码放在网络摄像头区域时读取,当将代码移开时,不会捕获先前的结果。因此,如果成功,我想捕获第一个 QR 码并将其绑定到表单中以提交结果。我怎样才能正确地做到这一点?
到目前为止,这是我的代码:
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 纯代码包装到打字稿中;这是我的模板:
<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 控制器:
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));
}
推荐阅读
- sql - 如何使用 case 语句在 select 语句中应用 datediff 函数
- python - 如何打乱元组列表?
- python - 导出到 csv 文件时如何阻止数据溢出到下一行以及如何使用 Python 捕获 HTTP 错误
- android - 根据从 Firebase 收到的命令重新启动活动
- java - 如何解析具有列表的对象
- python - Pandas DataFrame 将数据从 BST/时钟转换为 GMT/UTC,反之亦然
- python - 在具有自定义数据类型的 python 包装的 C 函数上使用 autograd
- audio - 如何在 Flutter 应用中录制蓝牙耳机的音频
- xml - QML XmlListModel:使用属性查询节点
- swift - 在变量上使用 didSet 时如何停止 nil 可选值?