ZXing-js无法扫描EAN-13条码 求可用示例代码
解决ZXing-js无法扫描EAN-13条码的问题(.NET 4.8 MVC)
问题诊断
你的代码中存在几个可能导致EAN-13扫描失败的问题:
- 使用的ZXing版本(0.18.6)较旧,对EAN-13的兼容性可能不足
- 设备选择逻辑错误:
videoInputDevices是数组,直接取deviceId会导致未定义,应该选择具体设备(比如第一个摄像头) - 格式配置的传递方式不符合新版本API要求
- 持续扫描未在成功后停止,可能干扰后续识别
修正后的可运行示例代码
@model Pocos.MCD_Stores @{ ViewBag.Title = "DoVisit"; } <label id="recordCountLabel">Records Loaded: 0</label> <br /> <h2>Do Visit</h2> <!-- 扫描控制按钮 --> <button id="startScanButton">启动扫描</button> <button id="scanNowButton" style="display: none;">立即扫描</button> <button id="resetButton">重置</button> <br /> <!-- 扫描视频窗口 --> <video id="barcode-scanner" width="600" height="400" style="border: 1px solid gray; display: block;"></video> <br /> <!-- 扫描结果显示 --> <label id="scannedBarcodeLabel">扫描条码: 无</label> <br /> <label id="productDetailsLabel">产品详情: 无</label> <br /> <!-- 产品下拉框 --> <select id="productDropdown" style="width: 100%;"> <option value="">选择产品</option> </select> <link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" /> <!-- 升级到较新的ZXing版本 --> <script src="https://cdn.jsdelivr.net/npm/@zxing/library@0.20.0/umd/index.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script> <script> let selectedDeviceId; let currentScanListener = null; // 初始化条码阅读器,指定仅支持EAN-13 const codeReader = new ZXing.BrowserMultiFormatReader(); // 配置阅读器优先识别EAN-13 codeReader.setPossibleFormats([ZXing.BarcodeFormat.EAN_13]); console.log('ZXing条码阅读器已初始化'); document.getElementById('startScanButton').addEventListener('click', () => { codeReader.listVideoInputDevices() .then(videoInputDevices => { // 处理多摄像头情况,默认选第一个可用摄像头 if (videoInputDevices.length === 0) { alert('未检测到摄像头设备'); return; } selectedDeviceId = videoInputDevices[0].deviceId; console.log('选择摄像头:', videoInputDevices[0].label); // 启动持续扫描,成功后自动停止 currentScanListener = codeReader.decodeFromVideoDevice(selectedDeviceId, 'barcode-scanner', (result, err) => { if (result) { console.log('检测到条码:', result); document.getElementById('scannedBarcodeLabel').innerText = `扫描条码: ${result.text}`; handleScannedBarcode(result.text); // 扫描成功后停止,避免重复触发 codeReader.reset(); document.getElementById('scanNowButton').style.display = 'none'; } if (err && !(err instanceof ZXing.NotFoundException)) { console.error('扫描错误:', err); } }); document.getElementById('scanNowButton').style.display = 'block'; }) .catch(err => console.error('获取摄像头列表失败:', err)); }); document.getElementById('scanNowButton').addEventListener('click', () => { if (!selectedDeviceId) { alert('请先启动扫描'); return; } // 单次扫描模式 codeReader.decodeOnceFromVideoDevice(selectedDeviceId, 'barcode-scanner') .then(result => { if (result) { console.log('检测到条码:', result); document.getElementById('scannedBarcodeLabel').innerText = `扫描条码: ${result.text}`; handleScannedBarcode(result.text); } }) .catch(err => { if (err && !(err instanceof ZXing.NotFoundException)) { console.error('单次扫描错误:', err); } else { alert('未检测到EAN-13条码,请调整位置重试'); } }); }); document.getElementById('resetButton').addEventListener('click', () => { codeReader.reset(); document.getElementById('scannedBarcodeLabel').innerText = '扫描条码: 无'; document.getElementById('productDetailsLabel').innerText = '产品详情: 无'; document.getElementById('scanNowButton').style.display = 'none'; currentScanListener = null; }); // 处理扫描到的条码逻辑(保留原有代码) function handleScannedBarcode(barcode) { const productDbRequest = indexedDB.open('ProductDatabase', 1); productDbRequest.onsuccess = (event) => { const db = event.target.result; const transaction = db.transaction('products', 'readonly'); const objectStore = transaction.objectStore('products'); const getRequest = objectStore.get(barcode); getRequest.onsuccess = (event) => { const product = event.target.result; if (product) { document.getElementById('productDetailsLabel').innerText = `产品详情: ${JSON.stringify(product)}`; storeScannedProduct(product.Sku); } else { document.getElementById('productDetailsLabel').innerText = `产品详情: 未找到`; } }; getRequest.onerror = (event) => { console.error('获取产品失败:', event.target.error); }; }; productDbRequest.onerror = (event) => { console.error('打开产品数据库失败:', event.target.error); }; } function customMatcher(params, data) { if ($.trim(params.term) === '') { return data; } const term = params.term.toLowerCase(); const text = data.text.toLowerCase(); if (text.indexOf(term) > -1) { return data; } return null; } function storeScannedProduct(sku) { const scannedDbRequest = indexedDB.open('scannedProductDatabase', 1); scannedDbRequest.onsuccess = (event) => { const db = event.target.result; const transaction = db.transaction('skuCounts', 'readwrite'); const objectStore = transaction.objectStore('skuCounts'); const getRequest = objectStore.get(sku); getRequest.onsuccess = (event) => { const record = event.target.result; if (record) { record.Count += 1; objectStore.put(record); } else { objectStore.put({ Sku: sku, Count: 1 }); } }; getRequest.onerror = (event) => { console.error('获取扫描记录失败:', event.target.error); }; }; scannedDbRequest.onerror = (event) => { console.error('打开扫描记录数据库失败:', event.target.error); }; } document.addEventListener('DOMContentLoaded', (event) => { initScannedProductDB() .then(db => { console.log('扫描记录数据库已就绪'); const recordCount = localStorage.getItem('recordCount'); if (recordCount) { document.getElementById('recordCountLabel').innerText = `已加载记录数: ${recordCount}`; } }) .catch(error => { console.error('初始化扫描记录数据库失败:', error); }); fetchProductsFromIndexedDB().then(products => { products.sort((a, b) => { const descA = a.Desc !== "NULL" ? a.Desc.toLowerCase() : ""; const descB = b.Desc !== "NULL" ? b.Desc.toLowerCase() : ""; if (descA < descB) return -1; if (descA > descB) return 1; return 0; }); const dropdown = $('#productDropdown'); products.forEach(product => { const desc = product.Desc !== "NULL" ? product.Desc : ""; const colour = product.Colour !== "NULL" ? product.Colour : ""; const size = product.Size !== "NULL" ? product.Size : ""; const option = new Option(`${desc} - ${colour} - ${size}`, product.Sku, false, false); dropdown.append(option); }); dropdown.select2({ placeholder: "选择产品", allowClear: true, matcher: customMatcher }); }).catch(error => { console.error('获取产品列表失败:', error); }); }); function initScannedProductDB() { return new Promise((resolve, reject) => { const request = indexedDB.open('scannedProductDatabase', 1); request.onupgradeneeded = (event) => { const db = event.target.result; const objectStore = db.createObjectStore('skuCounts', { keyPath: 'Sku' }); objectStore.createIndex('Sku', 'Sku', { unique: true }); objectStore.createIndex('Count', 'Count', { unique: false }); }; request.onsuccess = (event) => { console.log('扫描记录数据库初始化成功'); resolve(event.target.result); }; request.onerror = (event) => { reject(event.target.error); }; }); } function fetchProductsFromIndexedDB() { return new Promise((resolve, reject) => { const request = indexedDB.open('ProductDatabase', 1); request.onsuccess = (event) => { const db = event.target.result; const transaction = db.transaction(['products'], 'readonly'); const objectStore = transaction.objectStore('products'); const products = []; objectStore.openCursor().onsuccess = (event) => { const cursor = event.target.result; if (cursor) { products.push(cursor.value); cursor.continue(); } else { resolve(products); } }; objectStore.openCursor().onerror = (event) => { reject(event.target.error); }; }; request.onerror = (event) => { reject(event.target.error); }; }); } </script>
关键修改说明
- 升级ZXing版本:从0.18.6升级到0.20.0,修复了旧版本对EAN-13的识别兼容问题
- 正确设置格式:使用
codeReader.setPossibleFormats([ZXing.BarcodeFormat.EAN_13])替代原API的格式参数传递,符合新版本要求 - 修复设备选择逻辑:处理多摄像头场景,默认选择第一个可用设备,避免
deviceId未定义的错误 - 优化扫描行为:持续扫描成功后自动停止,避免重复触发识别;单次扫描失败时给出友好提示
- 添加错误处理:补充摄像头未检测到的提示,增强用户体验
额外调试建议
- 确保EAN-13条码清晰,无模糊或反光
- 调整摄像头与条码的距离(建议10-30cm),确保条码完整出现在视频窗口中
- 在浏览器控制台查看是否有设备权限或视频流错误
- 尝试切换前后摄像头,部分设备前置摄像头分辨率较低可能影响识别
内容的提问来源于stack exchange,提问作者Jim Tench
相关产品推荐
相关产品推荐

