本文介绍如何基于javascript开发chrome/firefox扩展,通过截取网页指定区域的屏幕图像并解析其中的qr码,核心步骤包括定位qr元素、截图转canvas数据、调用js解码库(如jsqr),全程不依赖摄像头。
本文介绍如何基于javascript开发chrome/firefox扩展,通过截取网页指定区域的屏幕图像并解析其中的qr码,核心步骤包括定位qr元素、截图转canvas数据、调用js解码库(如jsqr),全程不依赖摄像头。
要在浏览器扩展中实现“屏幕内QR码识别”(即从网页内容而非摄像头画面中读取QR码),关键在于将视觉识别流程拆解为定位 → 截图 → 解码三步闭环,并合理分配逻辑到扩展的不同运行环境(content script + background service worker)。以下是可立即上手的实践路径:
首先需让内容脚本智能识别页面中可能包含QR码的DOM节点——常见形式包括 <img>(含base64或URL二维码)、<canvas>(动态渲染的二维码)、<svg> 或带 data-qr 属性的容器。示例代码:
// content.tsfunction findQRElements() { const candidates = [ ...document.querySelectorAll('img[src*="data:image/png;base64"], img[src*="qrcode"]'), ...document.querySelectorAll('canvas.qr-code, canvas[data-qr]'), ...document.querySelectorAll('[data-qr-src], [aria-label*="QR"]') ]; return candidates.map(el => ({ rect: el.getBoundingClientRect(), node: el }));}// 向background发送位置信息(含坐标、尺寸、必要时截图DataURL)chrome.runtime.sendMessage({ type: 'SCAN_QR_REGION', regions: findQRElements().map(({ rect }) => ({ x: rect.left, y: rect.top, width: rect.width, height: rect.height, scrollX: window.scrollX, scrollY: window.scrollY }))});
Background端接收坐标后,使用 chrome.tabs.captureVisibleTab() 或更精准的 chrome.tabs.captureTab()(需 "tabs" 权限)获取当前标签页可视区域截图;再用Canvas裁剪目标区域并转换为 ImageData:
// background.tschrome.runtime.onMessage.addListener(async (req, sender, sendResponse) => { if (req.type === 'SCAN_QR_REGION' && req.regions.length > 0) { const tab = await chrome.tabs.get(sender.tab.id); const screenshot = await chrome.tabs.captureTab(tab.id, { format: 'png' }); const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); const img = new Image(); img.onload = () => { // 按坐标裁剪(注意:需考虑页面滚动偏移与缩放) const scale = window.devicePixelRatio || 1; canvas.width = req.regions[0].width * scale; canvas.height = req.regions[0].height * scale; ctx.drawImage( img, req.regions[0].x * scale, req.regions[0].y * scale, req.regions[0].width * scale, req.regions[0].height * scale, 0, 0, canvas.width, canvas.height ); const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); // → 传入解码器 decodeQR(imageData).then(result => { sendResponse({ success: true, data: result }); }).catch(err => { sendResponse({ success: false, error: err.message }); }); }; img.src = screenshot; } return true; // 保持异步响应通道开启});
推荐使用轻量、纯JS、无依赖的 jsQR(Authenticator实际主力库),它直接接受 Uint8ClampedArray 格式的灰度图像数据:
import jsQR from 'jsqr';function decodeQR(imageData) { const code = jsQR( imageData.data, imageData.width, imageData.height, { inversionAttempts: 'dontInvert' } ); return code ? Promise.resolve(code.data) : Promise.reject(new Error('No QR code found'));}
⚠️ 注意事项:
综上,你无需重造轮子——以 Authenticator 的架构为蓝本,聚焦于 content script 的智能发现 + background 的精准截图 + jsQR 的高效解码,即可快速构建出稳定可靠的屏幕QR阅读器。从监听用户右键 → 获取选中区域 → 截图解码 → 弹出结果,整个链路完全可控且易于调试。