A high-performance barcode scanner React component with optimized detection, camera switching, torch control, and automatic phone detection.
- π High Performance: Web Worker-based scanning with optimized grayscale conversion.
- π± Mobile Optimized: Automatic phone detection with appropriate camera selection.
- π¦ Torch Control: Built-in torch/flash support for low-light scanning.
- π Camera Switching: Easy switching between front and back cameras.
- π· Smart Camera Selection: Automatically selects the best rear camera (avoids ultra-wide/telephoto).
- π― Session Management: Prevents stale results with session-based tracking.
- π¨ Customizable UI: CSS-based styling with sensible defaults and CSS variables.
- π¦ TypeScript Support: Full type definitions included out of the box.
- π³ Haptic Feedback: Standard Web Vibration API support for successful scans (Android/Desktop).
- π Sound Feedback: Optional audio cues on successful scans.
- 2D Codes: QR Code, PDF417
- Retail Codes: EAN-13, EAN-8, UPC-A, UPC-E
- Industrial/Standard Codes: Code 128, Code 39, Code 93, Codabar, ITF (Interleaved 2 of 5)
- Books: ISBN-10, ISBN-13
- DataBar (GS1)
- And more! (Powered by ZBar)
Choose your preferred package manager:
# npm
npm install modern-barcode-scanner
# yarn
yarn add modern-barcode-scanner
# pnpm
pnpm add modern-barcode-scannerHere's a minimal example to get the scanner up and running in your React application:
import { useRef, useEffect } from 'react';
import { BarcodeScanner, BarcodeScannerRef, ScanResult } from 'modern-barcode-scanner';
// Styles are auto-imported, but you can also import manually if needed:
// import 'modern-barcode-scanner/styles.css';
function App() {
const scannerRef = useRef<BarcodeScannerRef>(null);
const handleScan = (result: ScanResult) => {
console.log('π¦ Barcode type:', result.typeName);
console.log('π Barcode data:', result.scanData);
// Scanner automatically stops after detection.
// Call scannerRef.current?.start() to scan again!
};
const handleError = (error: Error) => {
console.error('β Scanner error:', error.message);
};
useEffect(() => {
// Start scanning when component mounts
scannerRef.current?.start();
}, []);
return (
<div style={{ width: '100vw', height: '100vh' }}>
<BarcodeScanner
ref={scannerRef}
onScan={handleScan}
onError={handleError}
themeColor="#4db8a8" // Customize the primary UI color!
/>
</div>
);
}Under the hood, this library uses @undecaf/zbar-wasm which relies on WebAssembly. Depending on your bundler, you may need to explicitly exclude it from dependency optimization or configure it to serve .wasm files correctly.
Vite Example (vite.config.ts):
export default defineConfig({
// ... other config
optimizeDeps: {
exclude: ['@undecaf/zbar-wasm']
}
});| Prop | Type | Default | Description |
|---|---|---|---|
onScan |
(result: ScanResult) => void |
Required | Callback fired when a barcode is detected. |
onError |
(error: Error) => void |
undefined |
Callback fired when an error occurs. |
onStateChange |
(state: ScannerState) => void |
undefined |
Callback fired when scanner state changes. |
themeColor |
string |
'#4db8a8' |
Primary theme color for UI elements and scan line. |
scanInterval |
number |
100 |
Time between scan attempts (in ms). |
enableVibration |
boolean |
true |
Enable haptic feedback on scan (uses navigator.vibrate). |
vibrationDuration |
number |
200 |
Vibration duration (in ms). |
enableSound |
boolean |
false |
Enable sound feedback on scan. |
initialFacingMode |
'user' | 'environment' |
'environment' |
Initial camera to use. |
showScanLine |
boolean |
true |
Show scanning animation line. |
showCameraSwitch |
boolean |
true |
Show camera switch button. |
showTorchButton |
boolean |
true |
Show torch button (if supported). |
className |
string |
'' |
Custom CSS class for the container. |
style |
React.CSSProperties |
undefined |
Custom inline styles for the container. |
Exposed via useImperativeHandle for direct control:
interface BarcodeScannerRef {
start: () => Promise<void>; // Starts the camera and scanning
stop: () => void; // Stops the camera and scanning
switchCamera: () => Promise<void>; // Toggles between front and back camera
toggleTorch: () => Promise<void>; // Toggles the torch/flash (if supported)
getState: () => ScannerState; // Returns current state
}interface ScanResult {
typeName: string; // e.g., 'QRCODE', 'EAN13', 'CODE128'
scanData: string; // The decoded barcode string
}
interface ScannerState {
isScanning: boolean;
facingMode: 'user' | 'environment';
isTorchOn: boolean;
}If you need complete control over the UI, you can use the internal hook directly:
import { useScanner } from 'modern-barcode-scanner';
function CustomScanner() {
const {
scannerState,
videoRef,
canvasRef,
handleScan,
handleStopScan,
handleSwitchCamera,
handleToggleTorch,
} = useScanner({
onScan: (result) => console.log('Scanned:', result),
onError: (error) => console.error('Error:', error),
enableVibration: true,
});
return (
<div>
<video ref={videoRef} autoPlay muted playsInline />
<canvas ref={canvasRef} hidden />
<div className="controls">
<button onClick={handleScan}>βΆοΈ Start</button>
<button onClick={handleStopScan}>βΉοΈ Stop</button>
<button onClick={handleSwitchCamera}>π Switch</button>
{scannerState.isTorchOn ? 'π¦ On' : 'π¦ Off'}
</div>
</div>
);
}The library exports several useful utilities:
import {
isPhone,
getBestRearCamera,
getMediaConstraints
} from 'modern-barcode-scanner';
// π± Check if device is a phone/tablet
const isMobile = isPhone();
// π· Get the optimal rear camera device ID (avoids ultra-wide lenses)
const cameraId = await getBestRearCamera();
// βοΈ Get optimized media constraints based on facing mode
const constraints = await getMediaConstraints('environment');The component uses CSS prefix mbs- (Modern Barcode Scanner) and supports native CSS variables for easy theming.
You can easily override the primary color globally or via the themeColor prop:
:root {
--mbs-primary: #ff0055; /* Changes scan line and active icon colors */
}/* Custom container styling */
.mbs-container {
border-radius: 1rem;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
}
/* Custom scan line */
.mbs-scan-line {
height: 3px;
box-shadow: 0 0 15px 3px var(--mbs-primary);
}
/* Custom control buttons */
.mbs-control-btn {
background-color: rgba(255, 255, 255, 0.2);
backdrop-filter: blur(4px);
}| Browser / OS | Version |
|---|---|
| π’ Google Chrome | 79+ |
| π΅ Microsoft Edge | 79+ |
| π Mozilla Firefox | 79+ |
| π§ Safari (macOS) | 14.1+ |
| π± Chrome for Android | Supported |
| π Safari on iOS | 14.5+ |
β οΈ Note: Camera access requires a secure context (HTTPS) in production environments!
This library is built for speed and reliability:
- Web Worker Processing: Barcode detection runs entirely off the main thread.
- Grayscale Conversion: Uses bitwise operations for incredibly fast image matrix processing.
- Frame Throttling: Configurable
scanIntervalperfectly balances detection speed with device battery/CPU usage. - Session Management: Strictly prevents processing out-of-date or stale video frames.
- Smart Downscaling: Intelligently reduces image resolution for faster processing while maintaining read quality.
- Canvas Optimizations: Utilizes
willReadFrequentlyanddesynchronizedrendering hints where supported.
MIT Β© Sumit Sahoo
Please refer to the LICENSE file for the full text.
- Powerful barcode detection engine powered by ZBar WASM.