id-scanner-lib
Version:
一款纯前端实现的TypeScript身份证&二维码识别库,无需后端支持,所有处理在浏览器端完成,新增图像批处理与优化
180 lines (162 loc) • 4.57 kB
text/typescript
/**
* @file 二维码和条形码扫描模块
* @description 包含二维码和条形码扫描功能
* @module IDScannerQR
* @version 1.0.0
* @license MIT
*/
import { QRScanner, QRScannerOptions } from "./scanner/qr-scanner"
import {
BarcodeScanner,
BarcodeScannerOptions,
} from "./scanner/barcode-scanner"
import { Camera, CameraOptions } from "./utils/camera"
/**
* 扫描模块配置选项
*/
export interface ScannerModuleOptions {
cameraOptions?: CameraOptions
qrScannerOptions?: QRScannerOptions
barcodeScannerOptions?: BarcodeScannerOptions
onQRCodeScanned?: (result: string) => void
onBarcodeScanned?: (result: string) => void
onError?: (error: Error) => void
}
/**
* 扫描模块类
*
* 提供独立的二维码和条形码扫描功能
*/
export class ScannerModule {
private qrScanner: QRScanner
private barcodeScanner: BarcodeScanner
private camera: Camera
private scanMode: "qr" | "barcode" | null = null
private videoElement: HTMLVideoElement | null = null
/**
* 构造函数
* @param options 配置选项
*/
constructor(private options: ScannerModuleOptions = {}) {
this.camera = new Camera(options.cameraOptions)
this.qrScanner = new QRScanner({
...options.qrScannerOptions,
onScan: this.handleQRScan.bind(this),
})
this.barcodeScanner = new BarcodeScanner({
...options.barcodeScannerOptions,
onScan: this.handleBarcodeScan.bind(this),
})
}
/**
* 启动二维码扫描
* @param videoElement HTML视频元素
*/
async startQRScanner(videoElement: HTMLVideoElement): Promise<void> {
this.stop() // 确保先停止可能正在运行的扫描
this.videoElement = videoElement
this.scanMode = "qr"
await this.camera.start(videoElement)
this.qrScanner.start(videoElement)
}
/**
* 启动条形码扫描
* @param videoElement HTML视频元素
*/
async startBarcodeScanner(videoElement: HTMLVideoElement): Promise<void> {
this.stop() // 确保先停止可能正在运行的扫描
this.videoElement = videoElement
this.scanMode = "barcode"
await this.camera.start(videoElement)
this.barcodeScanner.start(videoElement)
}
/**
* 停止扫描
*/
stop(): void {
if (this.scanMode === "qr") {
this.qrScanner.stop()
} else if (this.scanMode === "barcode") {
this.barcodeScanner.stop()
}
if (this.videoElement) {
this.camera.stop()
}
this.scanMode = null
}
/**
* 处理二维码扫描结果
*/
private handleQRScan(result: string): void {
if (this.options.onQRCodeScanned) {
this.options.onQRCodeScanned(result)
}
}
/**
* 处理条形码扫描结果
*/
private handleBarcodeScan(result: string): void {
if (this.options.onBarcodeScanned) {
this.options.onBarcodeScanned(result)
}
}
/**
* 处理错误
*/
private handleError(error: Error): void {
if (this.options.onError) {
this.options.onError(error)
} else {
console.error("ScannerModule error:", error)
}
}
/**
* 处理图像数据中的二维码
* @param imageData 要处理的图像数据
* @returns 返回Promise,解析为扫描结果
*/
async processQRCodeImage(imageData: ImageData): Promise<string> {
try {
const result = this.qrScanner.processImageData(imageData)
if (result) {
// 如果需要,触发回调
if (this.options.onQRCodeScanned) {
this.options.onQRCodeScanned(result)
}
return result
}
throw new Error("未检测到二维码")
} catch (error) {
this.handleError(error as Error)
throw error
}
}
/**
* 处理图像数据中的条形码
* @param imageData 要处理的图像数据
* @returns 返回Promise,解析为扫描结果
*/
async processBarcodeImage(imageData: ImageData): Promise<string> {
try {
const result = this.barcodeScanner.processImageData(imageData)
if (result) {
// 如果需要,触发回调
if (this.options.onBarcodeScanned) {
this.options.onBarcodeScanned(result)
}
return result
}
throw new Error("未检测到条形码")
} catch (error) {
this.handleError(error as Error)
throw error
}
}
}
// 导出相关类型和工具
export { QRScanner, QRScannerOptions } from "./scanner/qr-scanner"
export {
BarcodeScanner,
BarcodeScannerOptions,
} from "./scanner/barcode-scanner"
export { Camera, CameraOptions } from "./utils/camera"