Hi all,
I’m creating a pwa to scan a barcode and so far, I got this working
HTML:
<div>
<ion-button mode="md" size="large" expand="block" type="button" color="success" (click)="fileInput.click()">
<ion-icon slot="start" name="barcode-outline"></ion-icon>scan barcode
</ion-button>
<input style="display: none" #fileInput type="file" accept="image/*" (change)="preview($event)">
</div>
<div class="mb-3" *ngIf="previewUrl" align="center">
<br>
<img [src]="previewUrl" id="barcode" width="320"/>
</div>
<div align="center" *ngIf="scanResult">
<p style="font-weight: bolder; font-size: 25px; color: rgb(114, 114, 114);"> {{ scanResult }} </p>
</div>
<div align="center" *ngIf="scanError">
<p style="font-weight: bolder; font-size: 25px; color: rgb(114, 114, 114);"> {{ scanError }} </p>
</div>
TS:
@ViewChild("fileInput", { read: ElementRef, static: true }) fileInput: ElementRef;
scanResult = null;
scanError = null;
fileData: File = null;
previewUrl: any = null;
...
preview(fileInput: any) {
this.fileData = <File>fileInput.target.files[0];
// Show preview
if (this.fileData != undefined) {
if (this.fileData.type.match(/image\/*/)) {
var reader = new FileReader();
reader.readAsDataURL(this.fileData);
reader.onload = () => {
this.previewUrl = reader.result;
const codeReader = new ZXing.BrowserBarcodeReader();
console.log('barcode reader initialized');
const imgnew = new Image();
imgnew.src = this.previewUrl;
document.body.appendChild(imgnew);
codeReader
.decodeFromImage(imgnew)
.then(result => {
this.scanError = null;
console.log(result);
this.scanResult = result.getText();
})
.catch(err => {
this.scanResult = null;
this.scanError = err;
console.error(err);
});
},
reader.onerror = error => console.log(error);
}
}
}
The variabel “scanResult” is correct and gets immediately updated in the HTML.
But I need to resize the image to be able to decode the barcode on bigger images so I came up with this:
preview(fileInput: any) {
this.fileData = <File>fileInput.target.files[0];
if (this.fileData != undefined) {
if (this.fileData.type.match(/image\/*/)) {
const reader = new FileReader();
reader.readAsDataURL(this.fileData);
reader.onload = () => {
this.previewUrl = reader.result;
const img = new Image();
img.src = this.previewUrl;
img.onload = () => {
const elem = document.createElement('canvas');
const width = 320;
const scaleFactor = width / img.width;
elem.width = width;
elem.height = img.height * scaleFactor;
const ctx = elem.getContext('2d');
ctx.drawImage(img, 0, 0, width, img.height * scaleFactor);
ctx.canvas.toBlob(async (blob) => {
const file = new File([blob], 'barcode.jpeg', {
type: 'image/jpeg',
lastModified: Date.now()
});
const codeReader = new ZXing.BrowserBarcodeReader();
console.log('barcode reader initialized');
const imgnew = new Image();
imgnew.src = ctx.canvas.toDataURL(file.name);
document.body.appendChild(imgnew);
codeReader
.decodeFromImage(imgnew)
.then(result => {
this.scanError = null;
console.log(result);
this.scanResult = result.getText();
})
.catch(err => {
this.scanResult = null;
this.scanError = err;
console.error(err);
});
}, 'image/jpeg', 1);
},
reader.onerror = error => console.log(error);
}
}
}
}
The result still is correct, but my HTML does not get updated immediately anymore, only when I click the button again it is updated.
What am I doing wrong here ?