Build a Barcode and QR Code Scanner Using JavaScript and HTML5

If you are looking for a JavaScript barcode and QR code scanner SDK, Dynamsoft JavaScript Barcode SDK is no doubt the best. The SDK enables developers to quickly build web barcode and QR code scanner applications with a few lines of code. This article gives you a better understanding of Dynamsoft JavaScript Barcode Scanner.

SDK Activation

Documentation

JavaScript Barcode Scanner API

Getting Started with Dynamsoft JavaScript Barcode Scanner

The JavaScript Barcode Scanner is a part of Dynamsoft JavaScript Barcode SDK. It contains a built-in camera view which is optimized for real-time barcode and QR code scanning.

The "hello world" program is as follows:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width,initial-scale=1.0">
        <title>Dynamsoft JavaScript Barcode Scanner</title>
        <script src="https://cdn.jsdelivr.net/npm/dynamsoft-javascript-barcode@9.0.0/dist/dbr.js"></script>
    </head>
<body>
    <script>
        Dynamsoft.DBR.BarcodeReader.license = "DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ==";
        let scanner = null;
        (async()=>{
            scanner = await Dynamsoft.DBR.BarcodeScanner.createInstance();
            scanner.onFrameRead = results => {console.log(results);};
            scanner.onUnduplicatedRead = (txt, result) => {};
            await scanner.show();
        })();
    </script>
</body>
</html>

You can save the sample code to an index.html file and deploy it to a web server. Since HTML5 camera API requires HTTPS, you can use GitHub Pages to deploy the sample code.

The default barcode scanner UI consists of a camera source list, a camera resolution list, and a result overlay. In the following paragraphs, you will see how to customize the UI and adjust parameters to optimize the performance for barcode scanner.

Manually Loading the Library

Dynamsoft JavaScript Barcode Scanner is implemented using WebAssembly. Because it takes time to download and compile the wasm file, to avoid blocking UI, we can manually load the library after the page has been loaded:

<script>
    window.onload = async function () {
        try {
            await Dynamsoft.DBR.BarcodeScanner.loadWasm();
            await initBarcodeScanner();
        } catch (ex) {
            alert(ex.message);
            throw ex;
        }
    };
    let scanner = null;
    async function initBarcodeScanner() {
        scanner = await Dynamsoft.DBR.BarcodeScanner.createInstance();
        scanner.onFrameRead = results => {console.log(results);};
        scanner.onUnduplicatedRead = (txt, result) => {};
        await scanner.show();
    }
</script>

UI Customization

As you can see the default camera view is full-screen, which covers other HTML UI elements. To beautify the UI layout, we can append the scanner UI component to a DIV element:

<div id="barcodeScanner">
    <span id='loading-status' style='font-size:x-large'>Loading Library...</span>
</div>
<script>
    ...
    async function initBarcodeScanner() {
        scanner = await Dynamsoft.DBR.BarcodeScanner.createInstance();
        scanner.onFrameRead = results => {console.log(results);};
        scanner.onUnduplicatedRead = (txt, result) => {};
        document.getElementById('barcodeScanner').appendChild(scanner.getUIElement());
        document.getElementById('loading-status').hidden = true;
        await scanner.show();
    }
</script>

Or, replace the built-in UI element with our own UI element:

<div class="dce-video-container" id="videoContainer"></div>

<script>
    async function initBarcodeScanner() {
        scanner = await Dynamsoft.DBR.BarcodeScanner.createInstance();
        await scanner.setUIElement(document.getElementById('videoContainer'));
    }
</script>

If you want to hide the close button, change its hidden attribute to true:

document.getElementsByClassName('dbrScanner-sel-camera')[0].hidden = true;

To display the barcode result returned from onFrameRead, create a DIV element:

<div>
    Barcode Result: <a id='result'>N/A</a>
</div>
<script>
    ...
    scanner.onFrameRead = results => {
        console.log(results);
        for (let result of results) {
            document.getElementById('result').innerHTML = result.barcodeFormatString + ", " + result.barcodeText;
        }
    };
    ...
</script>

We use CSS to resize the camera view:

<style>
    body {
        display: flex;
        flex-direction: column;
        align-items: center;
    }

    #barcodeScanner {
        text-align: center;
        font-size: medium;
        height: 40vh;
        width: 40vw;
    }
</style>

barcode scanning result

After adding custom UI code, the barcode scanner looks more comfortable now.

Drawing Barcode Results on Overlay

The Barcode Scanner instance contains a built-in overlay used to render the barcode bounding box, but does not provide API for rendering barcode text results. In order to visually display the results, we can create a canvas as the overlay:

<style>
    #videoview {
        position: relative;
        width: 100%;
        height: 100vh;
    }

    #videoContainer {
        position: relative;
        width: 100%;
        height: 100%;
        z-index: 1
    }

    #overlay {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        z-index: 2;
        object-fit: contain
    }
</style>

<div id="videoview">
    <div class="dce-video-container" id="videoContainer"></div>
    <canvas id="overlay"></canvas>
</div>

The canvas size is the same as the video frame size. So we register the onPlayed event to update the canvas size dynamically:

function updateResolution() {
    if (scanner) {
        let resolution = scanner.getResolution();
        overlay.width = resolution[0];
        overlay.height = resolution[1];
    }
}

scanner.onPlayed = function () {
    updateResolution();
}

After getting the barcode and QR code results, draw the bounding box and text on the canvas:

function drawResult(context, localization, text) {
    context.beginPath();
    context.moveTo(localization.x1, localization.y1);
    context.lineTo(localization.x2, localization.y2);
    context.lineTo(localization.x3, localization.y3);
    context.lineTo(localization.x4, localization.y4);
    context.lineTo(localization.x1, localization.y1);
    context.stroke();

    context.font = '18px Verdana';
    context.fillStyle = '#ff0000';
    let x = [localization.x1, localization.x2, localization.x3, localization.x4];
    let y = [localization.y1, localization.y2, localization.y3, localization.y4];
    x.sort(function (a, b) {
        return a - b;
    });
    y.sort(function (a, b) {
        return b - a;
    });
    let left = x[0];
    let top = y[0];

    context.fillText(text, left, top + 50);
}

function showResults(results) {
    let context = clearOverlay();

    let txts = [];
    try {
        let localization;
        if (results.length > 0) {
            for (var i = 0; i < results.length; ++i) {
                txts.push(results[i].barcodeText);
                localization = results[i].localizationResult;
                drawResult(context, localization, results[i].barcodeText);
            }
            document.getElementById('result').innerHTML = txts.join(', ');
        }
        else {
            document.getElementById('result').innerHTML = "No barcode found";
        }

    } catch (e) {
        alert(e);
    }
}

scanner.onFrameRead = results => {
        showResults(results);
    };

With the overlay, the barcode scanner can provide a better user experience.

barcode scanner overlay

Optimize for QR Code Scanning

Dynamsoft JavaScript Barcode SDK supports multi-code decoding by default. It is common sense that the more barcode we decode simultaneously, the more performance loss we get. For specific scenarios that only require one kind of barcode symbologies, the runtime parameters can be further optimized.

We take QR Code as the example:

  • Set the barcode type as BF_QR_CODE:

      let settings = await scanner.getRuntimeSettings();
      settings.barcodeFormatIds = Dynamsoft.DBR.EnumBarcodeFormat.BF_QR_CODE;
      await scanner.updateRuntimeSettings(settings);
    
  • Change the deblur level to 0 and expected barcode count to 1:

      let settings = await scanner.getRuntimeSettings();
      settings.deblurLevel = 0;
      settings.expectedBarcodesCount = 1;
      await scanner.updateRuntimeSettings(settings);
    

Here is the best QR Code scanner we can finally have.

JavaScript Barcode Scanner for QR Code

Source Code