要在Web端实现基于摄像头的实时QR二维码扫描,需要包含摄像头控制和QR二维码解码两个部分的代码。Dynamsoft把这两部分封装在了一个JS SDK中,使用起来非常方便。
开发文档
https://www.dynamsoft.com/barcode-reader/programming/javascript/api-reference/BarcodeScanner.html?ver=latest
快速创建Web QR扫描程序
我们写一个最简单的hello world
程序。
<!DOCTYPE html>
<html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1.0"><title>Dynamsoft JavaScript Barcode Scanner</title><script src="https://cdn.jsdelivr.net/npm/dynamsoft-javascript-barcode@8.2.5/dist/dbr.js"></script></head>
<body><script>let scanner = null;(async()=>{scanner = await Dynamsoft.DBR.BarcodeScanner.createInstance();scanner.onFrameRead = results => {console.log(results);};scanner.onUnduplicatedRead = (txt, result) => {};await scanner.show();})();</script>
</body>
</html>
把代码保存到index.html
中,直接双击运行就行了。
这个程序是全屏显示的,而且第一次运行的时候会弹出提示框。有7天的免费试用期。如果需要更长的30天试用期,只需要通过账号申请一个ID就可以了。接下来分享下如何优化这个程序。
隐藏提示框
这个提示框跳出来可能很不爽,通过JS代码可以去掉:
<script>Dynamsoft.DBR.BarcodeScanner.showDialog = function () { };let scanner = null;
</script>
手动加载wasm文件
因为这个SDK是基于WebAssembly的,初始化的时间会比较长一些。所以可以在web页面初始化之后再加载:
<script>Dynamsoft.DBR.BarcodeScanner.showDialog = function () { };window.onload = async function () {try {await Dynamsoft.DBR.BarcodeScanner.loadWasm();await initBarcodeScanner();} catch (ex) {alert(ex.message);throw ex;}};let scanner = null;async function initBarcodeScanner() {scanner = await Dynamsoft.DBR.BarcodeScanner.createInstance();scanner.onFrameRead = results => {console.log(results);};scanner.onUnduplicatedRead = (txt, result) => {};await scanner.show();}
</script>
定制UI
正常使用的时候,摄像头的预览画面肯定不希望是全屏显示的。我们可以把摄像头的预览窗口放到一个DIV元素中:
<div id="barcodeScanner"><span id='loading-status' style='font-size:x-large'>Loading Library...</span>
</div>
<script>...async function initBarcodeScanner() {scanner = await Dynamsoft.DBR.BarcodeScanner.createInstance();scanner.onFrameRead = results => {console.log(results);};scanner.onUnduplicatedRead = (txt, result) => {};document.getElementById('barcodeScanner').appendChild(scanner.getUIElement());document.getElementById('loading-status').hidden = true;await scanner.show();}
</script>
注意到默认程序的右上角有一个关闭按钮,我们可以用代码隐藏:
document.getElementsByClassName('dbrScanner-sel-camera')[0].hidden = true;
创建一个DIV元素来显示扫码结果:
<div>Barcode Result: <a id='result'>N/A</a>
</div>
<script>...scanner.onFrameRead = results => {console.log(results);for (let result of results) {document.getElementById('result').innerHTML = result.barcodeFormatString + ", " + result.barcodeText;}};...
</script>
最后用CSS调整下布局:
<style>body {display: flex;flex-direction: column;align-items: center;}#barcodeScanner {text-align: center;font-size: medium;height: 40vh;width: 40vw;}
</style>
现在刷新页面,程序看起来好多了。
在摄像头预览窗口上绘制识别结果
SDK默认会把码的区域绘制出来,但是没有文字结果。打开开发者控制栏查看源码。
发现_drawRegionsults
函数是用来绘制结果的。我们重载这个函数,并增加文字绘制的逻辑:
...
for (let t of e) {let e = t.localizationResult;s.beginPath(),s.moveTo(e.x1, e.y1),s.lineTo(e.x2, e.y2),s.lineTo(e.x3, e.y3),s.lineTo(e.x4, e.y4),s.fill(),s.beginPath(),s.moveTo(e.x1, e.y1),s.lineTo(e.x2, e.y2),s.lineTo(e.x3, e.y3),s.lineTo(e.x4, e.y4),s.closePath(),s.stroke()let text = t.barcodeText;s.font = '18px Verdana';s.fillStyle = '#ff0000';let x = [e.x1, e.x2, e.x3, e.x4];let y = [e.y1, e.y2, e.y3, e.y4];x.sort(function (a, b) {return a - b;});y.sort(function (a, b) {return b - a;});let left = x[0];let top = y[0];s.fillText(text, left, top + 50);
}
...
再刷新下页面,体验好多了。
免费的Web端QR二维码扫描程序
如果你只是想体验Web端的QR二维码,以及其它条形码的扫描,可以在浏览器直接打开
https://demo.dynamsoft.com/barcode-reader-js/
源码
https://github.com/yushulx/javascript-barcode-scanner