Web App Barcode Scanner

Hi Logan

I’ve successfully added a Barcode / QR scanner using the “html-qrcode” npm package.

You need to implement it using a custom Element and this backend code, since it’s not possible to access the users camera using an iFrame Element:

class QRScanner extends HTMLElement {
    constructor() {
        super();
        const qrcodeScript = document.createElement("script");
        qrcodeScript.src = "https://unpkg.com/html5-qrcode@2.3.8/html5-qrcode.min.js";
        qrcodeScript.onload = this.initialize.bind(this);
        document.head.appendChild(qrcodeScript);
    }

    initialize() {
        this.innerHTML = `
            <style>
                @import url('https://fonts.googleapis.com/css2?family=Inter:wght@200;300;500;800&display=swap');
                #container {
                    display: flex;
                    flex-direction: column;
                    align-items: center;
                }
                #reader2 {
                background-color: #989AAD;    
                min-width: 301px;
                max-width: 301px;
                min-height: 180px;
                border-radius: 5px;
                cursor: not-allowed;
                display: flex;
                justify-content: center;
                align-items: center;
                }

                #button-container {
                    display: flex;
                    justify-content: space-between;
                    width: 100%;
                }
                #start-button {
                    background-color: #1476FF;
                    color: white;
                    font-size: 14px;
                    padding: 10px;
                    height: 45px;
                    border-radius: 5px;
                    color: white;
                    cursor: pointer;
                    font-family: 'Inter', sans-serif;
                    font-style: bold;
                    margin-right: 0px;
                    margin-top: 20px;
                }

                #stop-button {
                    background-color: white;
                    color: white;
                    font-size: 14px;
                    padding: 10px;
                    height: 45px;
                    border: 1px solid;
                    border-color: #E5E5EA; 
                    border-radius: 5px;
                    color: black;
                    cursor: pointer;
                    font-family: 'Inter', sans-serif;
                    font-style: bold;
                    margin-left: 0px;
                    margin-top: 20px;
                }

                #stop-button:hover {
                    background-color: #F8F8FB;
                    color: white;
                    padding: 10px;
                    height: 45px;
                    border: 1px solid;
                    border-color: #000000; 
                    border-radius: 5px;
                    color: black;
                    cursor: pointer;
                    font-family: 'Inter', sans-serif;
                    font-style: bold;
                }

                #start-button:hover {
                    background-color: #3D8DFD;
                    color: white;
                    padding: 10px;
                    border-radius: 5px;
                    color: white;
                    cursor: pointer;
                    font-family: 'Inter', sans-serif;
                    font-style: bold;
                }

                .icon {
                    background-image: url('https://static.wixstatic.com/shapes/4dedd8_05db8955cb124711987bf42071de2000.svg');
                    background-size: contain;
                    background-repeat: no-repeat;
                    width: 50px;
                    height: 50px;
                }

            </style>
            <div id="container">
                <div id="reader2" style="width: 320px; height: 180;">
                    <div class="icon"></div>
                </div>
                <div id="button-container">
                    <button id="stop-button">Abbrechen</button>
                    <button id="start-button">Scanner starten</button>
                </div>
            </div>
        `;

        this.querySelector('#start-button').addEventListener('click', () => this.startScanner());
        this.querySelector('#stop-button').addEventListener('click', () => this.stopScanner());
        // Bind the callbacks to the current instance
        this.qrCodeSuccessCallback = this.qrCodeSuccessCallback.bind(this);
        this.qrCodeErrorCallback = this.qrCodeErrorCallback.bind(this);
    }

    startScanner() {
        this.html5Qrcode = new Html5Qrcode("reader2");
        this.html5Qrcode.start(
            { facingMode: "environment" },
            { fps: 100, aspectRatio: 1.777779, qrbox: {width: 260, height: 100}, experimentalFeatures: { useBarCodeDetectorIfSupported: true } },
            this.qrCodeSuccessCallback,
            this.qrCodeErrorCallback
        );
    }

    stopScanner() {
        if (this.html5Qrcode) {
          this.html5Qrcode.stop().then(() => {
             this.html5Qrcode.clear();
             const reader = this.querySelector('#reader2');
             reader.innerHTML = '<div class="icon"></div>';
         }).catch(error => {
            console.error("Error stopping the QR scanner: ", error);
         });
        }
        this.dispatchEvent(new CustomEvent('stoppedScanner'));        
    }


    qrCodeSuccessCallback(decodedText, decodedResult) { 
        this.dispatchEvent(new CustomEvent('extractedBarcode', 
            { detail: `${decodedText}` }));
        this.html5Qrcode.stop()
    }

    qrCodeErrorCallback(error) {
    }
}

customElements.define("qr-scanner2", QRScanner);

You can customize almost anything and setup a custom flow, depending on your needs. Also you can customize which Codes are scanned (EAN13, QRCode, etc.) It’s best if you read the documentation: Documentation.

The scanner will look something like this:

Hope that helps :wink:

1 Like