How to Create a React Barcode and QR Code Scanning Library
In the previous article, we’ve built a React camera component. In this article, we are going to extend the camera component to create a React barcode and QR code scanning library using Dynamsoft Barcode Reader.
Create a React Barcode and QR Code Scanning Library
We are going to create a React barcode and QR code scanning component using Typescript.
New project
-
Init a new npm project.
npm init
-
Install dev dependencies.
npm install --save-dev typescript @types/react react react-dom
-
Install dependencies.
npm install dynamsoft-javascript-barcode react-vision-camera
Create the entry file and the component
-
Create a component named
src/BarcodeScanner.tsx
with the basic content:import React from 'react'; const BarcodeScanner = (): React.ReactElement => { return ( <div> Barcode Scanner </div> ) } export default BarcodeScanner;
-
Create an entry file named
src/index.js
with the following content:import BarcodeScanner from './BarcodeScanner' export * from "./BarcodeScanner" export { BarcodeScanner };
TypeScript configuration
-
Create a
tsconfig.json
file with the following content:{ "compilerOptions": { "target": "es2015", "lib": [ "dom", "dom.iterable", "esnext" ], "allowJs": true, "baseUrl": ".", "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "jsx": "react", "module": "commonjs", "moduleResolution": "node", "resolveJsonModule": true, "skipLibCheck": true, "strict": true, "declaration": true, "strictNullChecks": false, "outDir": "dist", "rootDir": "src" }, "exclude": [ "node_modules", "cypress" ], "include": [ "src/**/*" ] }
-
Update the
package.json
file to add a build script."scripts": { "build": "tsc" }
Now, we can run npm run build
to build the library.
Create an example project to test the component
We can create a new project to test the component.
-
New project with Create React App in the component project’s folder.
npx create-react-app example --template typescript
-
Install the component.
npm install ../
-
Use
npm link
to use the React in the component project’snode_modules
.npm link ../node_modules/react npm link ../node_modules/react-dom
-
Update
App.tsx
to use the barcode scanner component.import React from 'react'; import {BarcodeScanner} from 'react-barcode-qrcode-scanner'; function App() { return ( <div> <BarcodeScanner></BarcodeScanner> </div> ); } export default App;
-
We can now run the example project to test the component.
npm run start
Implement the barcode scanner component
Define props for the component
Extend the camera component’s props to add the following props.
export interface ScannerProps extends CameraProps{
runtimeSettings?: string;
license?: string;
interval?:number;
drawOverlay?: boolean;
onInitialized?: (reader:BarcodeReader) => void;
onScanned?: (results:TextResult[]) => void;
onClicked?: (result:TextResult) => void;
}
runtimeSettings
: runtime settings in JSON format which is used to update the barcode reader’s runtime settings, like specifying a barcode format.license
: license for Dynamsoft Barcode Reader. You can apply for a trial license here.interval
: scan interval in milliseconds.drawOverlay
: whether to draw barcode overlay in SVG.onScanned
: event triggered when a frame is processed.onInitialized
: event triggered when Dynamsoft Barcode Reader is initialized.onClicked
: event triggered when a barcode overlay is clicked.
Add the camera component
-
Update the JSX with the following:
return ( <VisionCamera isActive={props.isActive} isPause={props.isPause} facingMode={props.facingMode} desiredCamera={props.desiredCamera} desiredResolution={props.desiredResolution} onOpened={onOpened} onClosed={onClosed} onDeviceListLoaded={props.onDeviceListLoaded} > {props.children} </VisionCamera> )
-
The
onOpened
andonClosed
events are intercepted for further usage.const camera = React.useRef(null); const onOpened = (cam:HTMLVideoElement,camLbl:string) => { camera.current = cam; if (props.onOpened) { props.onOpened(cam,camLbl); } } const onClosed = () => { if (props.onClosed) { props.onClosed(); } }
Initialize Dynamsoft Barcode Reader
When the component is mounted, initialize Dynamsoft Barcode Reader with a license and update the runtime settings if the runtimeSettings
props exists.
const reader = React.useRef(null);
const mounted = React.useRef(false);
React.useEffect(()=>{
const init = async () => {
if (props.license) {
BarcodeReader.license = props.license;
}else{
BarcodeReader.license = "DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ=="; // public trial license
}
BarcodeReader.engineResourcePath = "https://unpkg.com/dynamsoft-javascript-barcode@9.0.2/dist/";
reader.current = await BarcodeReader.createInstance();
if (props.runtimeSettings) {
await (reader.current as BarcodeReader).initRuntimeSettingsWithString(props.runtimeSettings);
}
if (props.onInitialized) {
props.onInitialized(reader.current);
}
}
init();
mounted.current = true;
},[])
Manage runtime settings
When the runtimeSettings
props is changed, update the runtime settings as well.
React.useEffect(()=>{
if (props.runtimeSettings && reader.current) {
(reader.current as BarcodeReader).initRuntimeSettingsWithString(props.runtimeSettings);
}
},[props.runtimeSettings])
Start scanning barcodes when the camera is opened
Here is the code:
const interval = React.useRef(null);
const startScanning = () => {
const decode = async () => {
if (decoding.current === false && reader.current && camera.current) {
decoding.current = true;
const results = await reader.current.decode(camera.current);
setBarcodeResults(results);
if (props.onScanned) {
props.onScanned(results);
}
decoding.current = false;
}
}
if (props.interval) {
interval.current = setInterval(decode,props.interval);
}else{
interval.current = setInterval(decode,40);
}
}
const onOpened = (cam:HTMLVideoElement,camLbl:string) => {
camera.current = cam;
startScanning();
if (props.onOpened) {
props.onOpened(cam,camLbl);
}
}
Stop scanning barcodes if the camera is closed
Here is the code:
const stopScanning = () => {
clearInterval(interval.current);
}
const onClosed = () => {
stopScanning();
if (props.onClosed) {
props.onClosed();
}
}
Draw barcode overlays
We can highlight scanned barcodes and QR codes using SVG. Here is the code to do this. You can learn more about SVG in this article.
const [viewBox, setViewBox] = React.useState("0 0 1280 720");
const renderSVGOverlay = () => {
if (props.drawOverlay === true && barcodeResults.length>0) {
return (
<svg
preserveAspectRatio="xMidYMid slice"
viewBox={viewBox}
xmlns="<http://www.w3.org/2000/svg>"
style={{
position:'absolute',
top: 0,
left: 0,
width:'100%',
height:'100%'}}>
{barcodeResults.map((result,idx) => (
<polygon key={"poly-"+idx} xmlns="<http://www.w3.org/2000/svg>"
points={getPointsData(result)}
onClick={() => onPolygonClicked(result)}
style={{
fill:"rgba(85,240,40,0.5)",
stroke: "green",
strokeWidth: 1
}}
/>
))}
{barcodeResults.map((result,idx) => (
<text key={"text-"+idx} xmlns="<http://www.w3.org/2000/svg>"
x={result.localizationResult.x1}
y={result.localizationResult.y1}
fill="red"
fontSize="20"
>{result.barcodeText}</text>
))}
</svg>
)
}
}
const onOpened = (cam:HTMLVideoElement,camLbl:string) => {
setViewBox("0 0 "+cam.videoWidth+" "+cam.videoHeight);
}
Then add it in the JSX:
return (
<VisionCamera
isActive={props.isActive}
isPause={props.isPause}
facingMode={props.facingMode}
desiredCamera={props.desiredCamera}
desiredResolution={props.desiredResolution}
onOpened={onOpened}
onClosed={onClosed}
onDeviceListLoaded={props.onDeviceListLoaded}
>
{props.children}
+ {renderSVGOverlay()}
</VisionCamera>
)
Update the example to use the barcode and QR code scanner component
Now, we can use the component in the example project to open the camera and start scanning barcodes and QR codes.
<div className="vision-camera">
<BarcodeScanner
isActive={true}
desiredCamera="back"
desiredResolution={{width:1280,height:720}}
onScanned={onScanned}
>
</BarcodeScanner>
</div>
You can check out the online demo to have a try.