Capacitor + QRScanner

This is what I use. Works well.

cozmo/jsQR: A pure javascript QR code reading library. This library takes in raw images and will locate, extract and parse any QR code found within. (github.com)

import jsQR from "jsqr";
...
    @ViewChild('video', { static: false }) video: ElementRef;
    @ViewChild('canvas', { static: false }) canvas: ElementRef;

    canvasElement: any;
    videoElement: any;
    canvasContext: any;

    ngAfterViewInit() {
        this.canvasElement = this.canvas.nativeElement;
        this.canvasContext = this.canvasElement.getContext('2d');
        this.videoElement = this.video.nativeElement;
    }
    async startScan() {
        // Not working on iOS standalone mode!
        const stream = await navigator.mediaDevices.getUserMedia({
            video: { facingMode: 'environment' }
        });

        this.videoElement.srcObject = stream;
        // Required for Safari
        this.videoElement.setAttribute('playsinline', true);

        this.loading = await this.loadingController.create({});
        await this.loading.present();

        this.videoElement.play();
        requestAnimationFrame(this.scan.bind(this));
    }

    async scan() {
        if (this.videoElement.readyState === this.videoElement.HAVE_ENOUGH_DATA) {
            if (this.loading) {
                await this.loading.dismiss();
                this.loading = null;
                this.scanActive = true;
            }

            this.canvasElement.height = this.videoElement.videoHeight;
            this.canvasElement.width = this.videoElement.videoWidth;

            this.canvasContext.drawImage(
                this.videoElement,
                0,
                0,
                this.canvasElement.width,
                this.canvasElement.height
            );
            const imageData = this.canvasContext.getImageData(
                0,
                0,
                this.canvasElement.width,
                this.canvasElement.height
            );
            const code = jsQR(imageData.data, imageData.width, imageData.height, {
                inversionAttempts: 'dontInvert'
            });

            if (code) {
                this.scanActive = false;
                this.scanResult = code.data;
                this.showQrToast();
            } else {
                if (this.scanActive) {
                    requestAnimationFrame(this.scan.bind(this));
                }
            }
        } else {
            requestAnimationFrame(this.scan.bind(this));
        }
    }

page

    <ion-button expand="block" (click)="startScan()" *ngIf="!scanActive && !scanResult">
        <ion-icon slot="start" name="qr-code-outline"></ion-icon>
        Start Scanning
    </ion-button>

    <ion-button expand="block" (click)="reset()" color="warning" *ngIf="scanResult">
        <ion-icon slot="start" name="refresh"></ion-icon>
        Reset
    </ion-button>

    <!-- Shows our camera stream -->
    <video #video [hidden]="!scanActive" width="100%"></video>

    <!-- Used to render the camera stream images -->
    <canvas #canvas hidden></canvas>

    <!-- Stop our scanner preview if active -->
    <ion-button expand="block" (click)="stopScan()" color="danger" *ngIf="scanActive">
        <ion-icon slot="start" name="close"></ion-icon>
        Stop Scanning
    </ion-button>

1 Like

this plugin works like a charm: https://github.com/phonegap/phonegap-plugin-barcodescanner

For some additional discussion, see https://github.com/capacitor-community/proposals/issues/53.