Blog by ScanApp Free online QR Code and Barcode scanner for web

Using Html5-qrcode with only Camera or File options

Html5-qrcode is a light-weight library to easily integrate QR code scanning functionality to any web application. You can find out more about the project and it’s implementation details on the project page on Github.

ScanApp is the end to end implementation of the library by the same author.

By default, the library allows two type of scanning options

  • Camera based scan
  • File based scan (Allows users to select any file on their device)
Screenshot of default config
Screenshot of the app with default configuraion, before my pull request.

Earlier, there was no option to change this default configuration i.e. developers who wanted to use the library had to show both camera and file scan options even if their use-case was limited to one of them. There were feature request to open this up as a configuration.

The feature request

This feature request was raised seeking the support for controlling what all scan type should be rendered when using the library.

This seemed like an impactful item for me to start contributing to this project.

I added a configuration in Html5QrcodeScanner to support this

I was able to add a new configuration option, such that the user can

  • Either use only Camera based scan
  • Or only File based scan
  • Or use both of them, this happens to be the default option as well.

To configure the feature with Html5QrcodeScanner, one need to simply set supportedScanTypes options like this.

let html5QrcodeScanner = new Html5QrcodeScanner(
    "reader", 
    { 
        fps: 10,
        qrbox: qrboxFunction,
        experimentalFeatures: {
            useBarCodeDetectorIfSupported: true
        },
        rememberLastUsedCamera: true,
        supportedScanTypes: [
            Html5QrcodeScanType.SCAN_TYPE_FILE, 
            Html5QrcodeScanType.SCAN_TYPE_CAMERA
        ],
        aspectRatio: 1.7777778
    });

Note that

{
    supportedScanTypes: [
        Html5QrcodeScanType.SCAN_TYPE_FILE, 
        Html5QrcodeScanType.SCAN_TYPE_CAMERA
    ]
}

Is this the relevant configuration here. Here’s example of different scenarios.

[1] User only needs the camera based scanning.

In this case, set the supportedScanTypes value like this.

supportedScanTypes: [ Html5QrcodeScanType.SCAN_TYPE_CAMERA ],

This will render the QR Scanner something like this

Screenshot of camera only config
Screenshot of app with camera only config.

[2] User only needs the file based scanning.

Here set the supportedScanTypes value like this.

{
    supportedScanTypes: [Html5QrcodeScanType.SCAN_TYPE_FILE]
}

This will render the QR Scanner something like this

Screenshot of file only config
Screenshot of app with file only config.

[3] User wants to support both camera and file based option

This is the default option! And unless you have specific need to disable one of the two, I recommend you to use this.

If we don’t set any value for supportedScanTypes, the library will support both scanning types by default.

Bonus: Set file based scanning as default option while supporting both

A bonus addition to the feature was that - the order of the config is also honoured by the library. If you want to support both file and camera based scanning options but want to define file based option as the default you can just configure supportedScanTypes like this

{
    supportedScanTypes: [
        Html5QrcodeScanType.SCAN_TYPE_FILE, 
        Html5QrcodeScanType.SCAN_TYPE_CAMERA
    ]
}

This will render the QR Scanner something like this

Screenshot of file first config
Screenshot of app with file first config.

Otherwise, by default the library renders camera based option as the default one.

Similarly, you can define camera based option to be the default one

This happens to be the default scenario as well. So if you do nothing explicitly, library will behave in this fashion only.

{
    supportedScanTypes: [
        Html5QrcodeScanType.SCAN_TYPE_CAMERA,
        Html5QrcodeScanType.SCAN_TYPE_FILE
    ]
}

If you pass arbitrary values, library will throw error!

I suppose this goes without saying!

If you provide values other than the supported ones - the library will throw error.

Summary

Developers can now modify the type of scanning method when using the Html5QrcodeScanner library.

  • Developers can choose to render only Camera support.
  • Developers can choose to render only File selection support.
  • Developers can choose to support both but select file or camera as the default option.

If you have any feedbacks, please share in comment section. For any bug report or feature request please report it to the html5-qrcode library directly.

Using Flash or Torch with Html5-Qrcode

Screenshot of implementation

html5-qrcode is a fairly used open source library for implementing QR Code or barcode scanner in a web application. It has 400K+ downloads on Github and going around 31K downloads/week on npm.

I authored this library in my university days and have been maintaining this project since 2014 (If I remember correctly).

Enough bragging, coming back to the topic …

Almost all smartphones today come with camera which is coupled with a flash light. It’s also used as a torch while recording videos. Most QR scanning applications that are available on Android or IOS have support for enabling torch while scanning. This seems useful when scanning a code in low light conditions.

The feature request

There was a feature request on the project Github tracker for adding the same functionality to html5-qrcode library.

This is very interesting usecase - as it shows the power of web around controlling low level hardware on smartphones.

Support added for Html5QrcodeScanner

Considering the value add for end users, I have added the support for using torch (when supported) to the end to end library (i.e. Html5QrcodeScanner).

The feature is added as yet another button which shows up if

  1. The feature is enabled from config (off by default).
  2. Torch control is supported on the given browser + device.

It looks something like this

Screenshot of implementation

You can try it on scanapp.org.

So far I have verified it to work on Android devices on browsers like Google Chrome and Samsung’s default internet browser. I have verified it to work on Pixel 6 Pro, Samsung Flip 4 devices and One Plus 10 Pro.

I have also verified it to not work on Chrome or Safari on IOS (on Iphone 13).

Why? Likely not supported in the implementation - need to verify!

The support was added with PR#570. It’s been published under version 2.2.6.

To enable the feature with Html5QrcodeScanner one simply need to set showTorchButtonIfSupported to true.

let html5QrcodeScanner = new Html5QrcodeScanner(
    "reader",
    {
        fps: 10,
        qrbox: {width: 250, height: 250},
        rememberLastUsedCamera: true,
        aspectRatio: 1.7777778,
        showTorchButtonIfSupported: true
    });

How it works?

And how to set flash or torch with Html5Qrcode library.

First this you need to check is if torch is supported. Weather or not torch is supported depends on the device, browser as well as the selected camera (often only back camera supports torch).

The idea is to see if torch is available on MediaTrackConstraints of the running video track. When the camera scan is running you can call getRunningTrackSettings() to verify if torch is supported.

/** Returns {@code true} if torch is supported. */
function isTorchSupported(html5Qrcode: Html5Qrcode): boolean {
    let settings = html5Qrcode.getRunningTrackSettings();
    return "torch" in settings;
}

If torch is indeed supported, the next step is to enable it. You can use applyVideoConstraints(..) API to request turning on torch.

let constraints: MediaTrackConstraints = {
    "torch": true,
    "advanced": [{ "torch": true }]
};
await html5Qrcode.applyVideoConstraints(constraints);
let settings = html5Qrcode.getRunningTrackSettings();

if (settings.torch === true) {
    // Torch was indeed enabled, succeess.
} else {
    // Failure.
    // Failed to set torch, why?
}

In a similar fashion, you can request turning off torch with the same API.

Why set twice?

"advanced": [{ "torch": true }]

For backwards compatibility sake!

Browser and device support

As shared before this feature seems to be supported on Android devices. I have verified this on at least three Android devices and one IOS device.

Here’s summary:

  • Support verified on several Android devices.

  • Support verified on following browsers in Android
    • Google Chrome
    • Samsung Internet Browser
    • Opera
    • Microsoft Edge
    • Brave Browser
    • Duck Duck Go Browser
  • Verified lack of support on following browsers in Android
    • Mozilla Firefox
  • Verified lack of support on Chrome and Safari on IOS (Iphone 13)

In case you get a chance to test on more devices using scanapp.org, please add information in comments. I’ll update this article accordingly.

Photo credits

Like this article?

If you like this article, you can find more of my articles on Medium. If you are already on Medium you can follow me and subscribe to my articles.

If you are not on Medium, you can join with my link. Medium will pay me a peice and that’d be helpful for me to write more such articles. Medium has articles from several awesome authors.

Setting dynamic QR box size in Html5-qrcode

mebjas/html5-qrcode is a fairly used open source library for implementing QR Code or barcode scanner in a web application.

Figure: User interface for Html5-qrcode using Html5QrcodeScanner class

The library provides two approaches for integrating QR code / bar code scanning with any web applications.

  1. Core library called Html5Qrcode which provide APIs for web developers to build the user interface upon and abstracts camera / permissions / QR code or barcode decoding.
  2. End to end UI for code scanning as well local image based scanning using Html5QrcodeScanner class.

One can simply setup a QR code scanning with following lines of code.

<!-- html -->
<div id="reader" width="600px"></div>
<script src="https://unpkg.com/html5-qrcode" type="text/javascript">
// Javascript code.

function onScanSuccess(decodedText, decodedResult) {
  // handle the scanned code as you like, for example:
  console.log(`Code matched = ${decodedText}`, decodedResult);
}

let config = { fps: 10, qrbox: {width: 250, height: 250} };
let html5QrcodeScanner = new Html5QrcodeScanner(
  "reader", config, /* verbose= */ false);
html5QrcodeScanner.render(onScanSuccess);

The qrbox config lets developers define the portion of the viewfinder that will be used for scanning. It’s supported both in Html5Qrcode as well as Html5QrcodeScanner class. Based on this value the library renders a box with shaded regions around it, allowing end-users to compose the scanning device around the QR code or barcodes.

qrbox configuration

Based on the developer documentation you can either pass a dimension of type QrDimensions as value for this config.

/** Defines dimension for QR Code Scanner. */
interface QrDimensions {
  width: number;
  height: number;
}

So this means for a barcode scanning usecase you can pass a non square configuration like {width: 400, height: 100} to render scanner like this - likely ideal for scanning rectangual barcodes.

Dynamically setting qrbox configuration

With version 2.2.0 onwards the library now also supports passing in a function of type QrDimensionFunction as a value for this configuration.

/**
 * A function that takes in the width and height of the video stream 
 * and returns QrDimensions.
 * 
 * Viewfinder refers to the video showing camera stream.
 */
type QrDimensionFunction =
    (viewfinderWidth: number, viewfinderHeight: number) => QrDimensions;

The function takes in the dimensions of the viewfinder (the video stream with camera feed) and is expected to return QrDimensions.

This is great, with this you can now set a custom function to determine the QR box dimensions based on run time properties of the video stream that works across form factors.

Here’s an example:

function onScanSuccess(decodedText, decodedResult) {
    // handle the scanned code as you like, for example:
    console.log(`Code matched = ${decodedText}`, decodedResult);
}

// Square QR box with edge size = 70% of the smaller edge of the viewfinder.
let qrboxFunction = function(viewfinderWidth, viewfinderHeight) {
    let minEdgePercentage = 0.7; // 70%
    let minEdgeSize = Math.min(viewfinderWidth, viewfinderHeight);
    let qrboxSize = Math.floor(minEdgeSize * minEdgePercentage);
    return {
        width: qrboxSize,
        height: qrboxSize
    };
}

let html5QrcodeScanner = new Html5QrcodeScanner(
    "reader",
    { fps: 10, qrbox: qrboxFunction },
    /* verbose= */ false);
html5QrcodeScanner.render(onScanSuccess);

With this you can set the QR box dimensions to always be 70% of the smaller edge of the video stream so it works on both mobile and PC platforms.

Open source library for QR Code and barcode scanning with ReactJs

This article has been forked from the original article by the Author at blog.minhazav.dev.


Introduction

I don’t think ReactJs needs any explanation here and throughout this article I’ll assume the readers have familiarity with React, Components, state, props etc.

If you are just interested in implementing QR code or barcode scanning on web without react, I recommend you read this article

Install the library using npm

First, install the latest version of the library in your React project, using npm

npm i html5-qrcode

Create a React component

Next step is to create a React that abstracts most of the scanner implementation. Let say we create a new file called Html5QrcodePlugin.jsx


// Html5QrcodePlugin.jsx

import { Html5QrcodeScanner } from "html5-qrcode";
import React from 'react';

const qrcodeRegionId = "html5qr-code-full-region";

class Html5QrcodePlugin extends React.Component {
    render() {
        return <div id={qrcodeRegionId} />;
    }

    componentWillUnmount() {
        // TODO(mebjas): See if there is a better way to handle
        //  promise in `componentWillUnmount`.
        this.html5QrcodeScanner.clear().catch(error => {
            console.error("Failed to clear html5QrcodeScanner. ", error);
        });
    }

    componentDidMount() {
        // Creates the configuration object for Html5QrcodeScanner.
        function createConfig(props) {
            var config = {};
            if (props.fps) {
            config.fps = props.fps;
            }
            if (props.qrbox) {
            config.qrbox = props.qrbox;
            }
            if (props.aspectRatio) {
            config.aspectRatio = props.aspectRatio;
            }
            if (props.disableFlip !== undefined) {
            config.disableFlip = props.disableFlip;
            }
            return config;
        }

        var config = createConfig(this.props);
        var verbose = this.props.verbose === true;

        // Suceess callback is required.
        if (!(this.props.qrCodeSuccessCallback )) {
            throw "qrCodeSuccessCallback is required callback.";
        }

        this.html5QrcodeScanner = new Html5QrcodeScanner(
            qrcodeRegionId, config, verbose);
        this.html5QrcodeScanner.render(
            this.props.qrCodeSuccessCallback,
            this.props.qrCodeErrorCallback);
    }
};

export default Html5QrcodePlugin;

Important note: html5-qrcode is an actively developed library. It’s advisable to subscribe to updates at mebjas/html5-qrcode so you can keep the React library up to date.

Use this plugin in your React App

I’ll assume you have an App.js that is the source component. You can add the new Component we just created.

class App extends React.Component {
    constructor(props) {
        super(props);

        // This binding is necessary to make `this` work in the callback.
        this.onNewScanResult = this.onNewScanResult.bind(this);
    }

    render() {
        return (<div>
            <h1>Html5Qrcode React example!</h1>
            <Html5QrcodePlugin 
                fps={10}
                qrbox={250}
                disableFlip={false}
                qrCodeSuccessCallback={this.onNewScanResult}/>
        </div>);
    }

    onNewScanResult(decodedText, decodedResult) {
        // Handle the result here.
    }
);

Passing around the callback

You might have seen the callback defined in the above section

// ... rest of the code 

    onNewScanResult(decodedText, decodedResult) {
        // Handle the result here.
    }

// ... rest of the code 

Use this callback to define rest of your business logic. Let say your use-case is to pass the newly scanned result and print in on a <table>, you’d want to pass around the data to a different component. You can find an example of this at scanapp-org/html5-qrcode-react.

Full code reference

The full example has been created at scanapp-org/html5-qrcode-react - you can use that as a good reference.

Credits

ScanApp - Free QR code and barcode scanner for web
scanapp.org is a free online QR code and barcode reader for web built using this library - try it out.

Closing note

I have to admit, I am not React savvy, if you see errors or know of better way to do things please suggest it using the comments or send a pull request to scanapp-org/html5-qrcode-react.