如何为你的手机网站创建一个二维码阅读器

条形码和二维码使我们的购物和搜索体验现代化。现在,携带智能手机的消费者可以在世界任何地方拿起一件商品,用众多免费手机应用中的一款扫描条形码或二维码,就能找到最低价格以及哪里可以买到。

带有条形码扫描器按钮的应用程序截图"title=

沃尔玛(Walmart)和亚马逊(Amazon)等公司已经采用了这一技术,通过手机应用程序将顾客吸引到他们的线上和线下商店。联邦快递(Fedex)和联合包裹(UPS)等其他公司允许顾客使用手机应用程序扫描包裹上的代码,而无需手动输入一长串字符。

如果你的手机网站的用户需要输入像激活码这样的长代码,或者他们喜欢根据杂志或广告上打印的型号号码在你的网站上查找特定的产品,那么你也可以利用QR码来消除小键盘的挫败感,让他们不必再次检查错误。

二维码扫描与您的移动网站

你不需要本地手机应用程序来扫描二维码。创建自己的二维码阅读器非常简单。在配备摄像头的智能手机上运行网站并运行一些JavaScript也能达到同样的效果。

这是一个演示这款二维码扫描仪不仅适用于手机,也适用于大多数现代设备。你所需要的只是一个摄像头和一个扫描二维码。

如果你手边没有二维码,这里有一个显示圆周率的前8位数字的二维码。

测试二维码阅读器:编码圆周率值的二维码"title=

创建二维码阅读器

我们的QR码阅读器将需要一些HTML和JavaScript,但最重要的是,一个JavaScript库能够解释QR码。

我们不打算自己构建它,因为有一些很棒的库可以为我们做这个,所以我们不需要为了我们当前的目的重新发明轮子。

让我们从创建一个index . html文件。

添加HTML

对于这个项目,我们需要一些非常简单的HTML。在body标签中添加以下内容:

<div<跨度class="token attr-name">id<跨度class="token attr-value"><跨度class="token punctuation">"容器<跨度class="token punctuation">"<跨度class="token punctuation">><跨度class="token tag"><h1<跨度class="token punctuation">>二维码扫描器<跨度class="token tag">h1<跨度class="token punctuation">><跨度class="token tag"><一个<跨度class="token attr-name">id<跨度class="token attr-value"><跨度class="token punctuation">"btn-scan-qr<跨度class="token punctuation">"<跨度class="token punctuation">><跨度class="token tag"><img<跨度class="token attr-name">src<跨度class="token attr-value"><跨度class="token punctuation">"https://uploads.必威西盟体育网页登录sitepoint.com/wp-content/uploads/2017/07/1499401426qr_icon.svg<跨度class="token punctuation">"<跨度class="token punctuation">><跨度class="token tag"><一个<跨度class="token punctuation">/><跨度class="token tag"><帆布<跨度class="token attr-name">隐藏的<跨度class="token attr-value"><跨度class="token punctuation">"<跨度class="token punctuation">"<跨度class="token attr-name">id<跨度class="token attr-value"><跨度class="token punctuation">"qr-canvas<跨度class="token punctuation">"<跨度class="token punctuation">><跨度class="token tag">帆布<跨度class="token punctuation">><跨度class="token tag"><div<跨度class="token attr-name">id<跨度class="token attr-value"><跨度class="token punctuation">"qr-result<跨度class="token punctuation">"<跨度class="token attr-name">隐藏的<跨度class="token attr-value"><跨度class="token punctuation">"<跨度class="token punctuation">"<跨度class="token punctuation">><跨度class="token tag"><b<跨度class="token punctuation">>数据:<跨度class="token tag">b<跨度class="token punctuation">><跨度class="token tag"><跨度<跨度class="token attr-name">id<跨度class="token attr-value"><跨度class="token punctuation">"outputData<跨度class="token punctuation">"<跨度class="token punctuation">><跨度class="token tag">跨度<跨度class="token punctuation">><跨度class="token tag">div<跨度class="token punctuation">><跨度class="token tag">div<跨度class="token punctuation">><跨度class="token tag"><脚本<跨度class="token attr-name">src<跨度class="token attr-value"><跨度class="token punctuation">"/ src / qrCodeScanner.js<跨度class="token punctuation">"<跨度class="token punctuation">><跨度class="token script">脚本<跨度class="token punctuation">>

如您所见,我们有一个带有标题的包装容器,QR图标图像包装在一个标签,帆布和一个div我们会在这里显示扫描结果。

容器外div我们包括qrCodeScanner.js文件。稍后我们将创建它,但首先我们将改进应用程序的外观。

添加样式

将样式表添加到HTML的头部:

<链接<跨度class="token attr-name">rel<跨度class="token attr-value"><跨度class="token punctuation">"样式表<跨度class="token punctuation">"<跨度class="token attr-name">href<跨度class="token attr-value"><跨度class="token punctuation">"src/ styles.css<跨度class="token punctuation">"<跨度class="token punctuation">/>

现在我们要创建style.css文件在src文件夹中。我们只是想要这个示例应用程序的一些基本样式。添加以下到你的css文件:

超文本标记语言<跨度class="token punctuation">{<跨度class="token property">高度<跨度class="token punctuation">:<跨度class="token number">One hundred.<跨度class="token unit">%<跨度class="token punctuation">;<跨度class="token punctuation">}<跨度class="token selector">身体<跨度class="token punctuation">{<跨度class="token property">字体类型<跨度class="token punctuation">:无衬线<跨度class="token punctuation">;<跨度class="token property">填充<跨度class="token punctuation">:<跨度class="token number">0<跨度class="token number">10<跨度class="token unit">px<跨度class="token punctuation">;<跨度class="token property">高度<跨度class="token punctuation">:<跨度class="token number">One hundred.<跨度class="token unit">%<跨度class="token punctuation">;<跨度class="token property">背景<跨度class="token punctuation">:<跨度class="token color">黑色的<跨度class="token punctuation">;<跨度class="token property">保证金<跨度class="token punctuation">:<跨度class="token number">0<跨度class="token punctuation">;<跨度class="token punctuation">}<跨度class="token selector">h1<跨度class="token punctuation">{<跨度class="token property">颜色<跨度class="token punctuation">:<跨度class="token color">白色<跨度class="token punctuation">;<跨度class="token property">保证金<跨度class="token punctuation">:<跨度class="token number">0<跨度class="token punctuation">;<跨度class="token property">填充<跨度class="token punctuation">:<跨度class="token number">15<跨度class="token unit">px<跨度class="token punctuation">;<跨度class="token punctuation">}<跨度class="token selector">#容器<跨度class="token punctuation">{<跨度class="token property">text-align<跨度class="token punctuation">:中心<跨度class="token punctuation">;<跨度class="token property">保证金<跨度class="token punctuation">:<跨度class="token number">0<跨度class="token punctuation">;<跨度class="token punctuation">}<跨度class="token selector"># qr-canvas<跨度class="token punctuation">{<跨度class="token property">保证金<跨度class="token punctuation">:汽车<跨度class="token punctuation">;<跨度class="token property">宽度<跨度class="token punctuation">:<跨度class="token function">calc<跨度class="token punctuation">(<跨度class="token number">One hundred.<跨度class="token unit">%<跨度class="token operator">-<跨度class="token number">20.<跨度class="token unit">px<跨度class="token punctuation">)<跨度class="token punctuation">;<跨度class="token property">max-width<跨度class="token punctuation">:<跨度class="token number">400<跨度class="token unit">px<跨度class="token punctuation">;<跨度class="token punctuation">}<跨度class="token selector"># btn-scan-qr<跨度class="token punctuation">{<跨度class="token property">光标<跨度class="token punctuation">:指针<跨度class="token punctuation">;<跨度class="token punctuation">}<跨度class="token selector"># btn-scan-qrimg<跨度class="token punctuation">{<跨度class="token property">高度<跨度class="token punctuation">:<跨度class="token number">10<跨度class="token unit">新兴市场<跨度class="token punctuation">;<跨度class="token property">填充<跨度class="token punctuation">:<跨度class="token number">15<跨度class="token unit">px<跨度class="token punctuation">;<跨度class="token property">保证金<跨度class="token punctuation">:<跨度class="token number">15<跨度class="token unit">px<跨度class="token punctuation">;<跨度class="token property">背景<跨度class="token punctuation">:<跨度class="token color">白色<跨度class="token punctuation">;<跨度class="token punctuation">}<跨度class="token selector"># qr-result<跨度class="token punctuation">{<跨度class="token property">字体大小<跨度class="token punctuation">:<跨度class="token number">1.2<跨度class="token unit">新兴市场<跨度class="token punctuation">;<跨度class="token property">保证金<跨度class="token punctuation">:<跨度class="token number">20.<跨度class="token unit">px汽车<跨度class="token punctuation">;<跨度class="token property">填充<跨度class="token punctuation">:<跨度class="token number">20.<跨度class="token unit">px<跨度class="token punctuation">;<跨度class="token property">max-width<跨度class="token punctuation">:<跨度class="token number">700<跨度class="token unit">px<跨度class="token punctuation">;<跨度class="token property">背景颜色<跨度class="token punctuation">:<跨度class="token color">白色<跨度class="token punctuation">;<跨度class="token punctuation">}

一点也不花哨。我们将把所有内容居中,中间有一个大的QR按钮,结果在下面。我们用的是像QR码一样的黑白。

包括依赖JavaScript库

阅读二维码的秘诀是数学,而数学的替代品是开源图书馆。要读取二维码,我们将使用<一个href="https://github.com/LazarSoft/jsqrcode">JavaScript港口基于java的<一个href="https://github.com/zxing/zxing">图像处理库作者:ZXingJavaScript版本由Lazar Laszlo移植。

由于JavaScript库由17个文件组成,我们擅自将它们合并到一个文件中,将代码包装在匿名函数中以防止全局名称空间的污染,并将文件通过谷歌Closure的minifier使文件大小更小。

库的一些小调整

为了使库的适应性更强,我们对库的输出函数进行了一些小更改,以区分成功响应和错误响应。

有两个重要的变化<一个href="https://github.com/sitepoint-editors/jsqrcode/blob/master/src/qrcode.js">qrcode.js,到这两行:

qrcode<跨度class="token punctuation">.<跨度class="token property-access">结果<跨度class="token operator">=<跨度class="token string">“错误解码二维码”<跨度class="token punctuation">;<跨度class="token comment">/ /……qrcode<跨度class="token punctuation">.<跨度class="token method function property-access">回调<跨度class="token punctuation">(<跨度class="token string">"加载图像失败"<跨度class="token punctuation">)<跨度class="token punctuation">;

这些字符串已经被错误对象:

qrcode<跨度class="token punctuation">.<跨度class="token property-access">结果<跨度class="token operator">=<跨度class="token known-class-name class-name">错误<跨度class="token punctuation">(<跨度class="token string">“错误解码二维码”<跨度class="token punctuation">)<跨度class="token punctuation">;<跨度class="token comment">/ /……qrcode<跨度class="token punctuation">.<跨度class="token method function property-access">回调<跨度class="token punctuation">(<跨度class="token known-class-name class-name">错误<跨度class="token punctuation">(<跨度class="token string">"加载图像失败"<跨度class="token punctuation">)<跨度class="token punctuation">)<跨度class="token punctuation">;

现在,我可以在回调函数中检测是否发生了错误,只需检查回调有效负载是否是的实例错误与否。

这些变化可以在<一个href="https://github.com/sitepoint-editors/jsqrcode/">这个叉图书馆的。

添加脚本标签

要在二维码阅读器中使用该库,我们首先需要使用常规脚本标记将其包含在HTML中:

<脚本<跨度class="token attr-name">src<跨度class="token attr-value"><跨度class="token punctuation">"https://rawgit.com/必威西盟体育网页登录sitepoint-editors/jsqrcode/master/src/qr_packed.js<跨度class="token punctuation">"<跨度class="token punctuation">><跨度class="token script">脚本<跨度class="token punctuation">>

将其视为应用程序

我们需要做的事情是告诉移动浏览器,我们不想以纵向模式缩放这个网站。控件中添加以下元标记可以实现这一点元素:

<<跨度class="token attr-name">的名字<跨度class="token attr-value"><跨度class="token punctuation">"视窗<跨度class="token punctuation">"<跨度class="token attr-name">内容<跨度class="token attr-value"><跨度class="token punctuation">"宽度=设备宽度;初始= 1.0;最大范围= 1.0;user-scalable = 0;<跨度class="token punctuation">"<跨度class="token punctuation">/>

添加脚本

现在我们需要创建qrCodeReader.jssrc文件夹,它应该与我们的HTML文件在同一级别。

让我们在新文件中添加一些代码:

常量qrcode<跨度class="token operator">=<跨度class="token dom variable">窗口<跨度class="token punctuation">.<跨度class="token property-access">qrcode<跨度class="token punctuation">;<跨度class="token keyword">常量视频<跨度class="token operator">=<跨度class="token dom variable">文档<跨度class="token punctuation">.<跨度class="token method function property-access">createElement<跨度class="token punctuation">(<跨度class="token string">“视频”<跨度class="token punctuation">)<跨度class="token punctuation">;<跨度class="token keyword">常量canvasElement<跨度class="token operator">=<跨度class="token dom variable">文档<跨度class="token punctuation">.<跨度class="token method function property-access">getElementById<跨度class="token punctuation">(<跨度class="token string">“qr-canvas”<跨度class="token punctuation">)<跨度class="token punctuation">;<跨度class="token keyword">常量帆布<跨度class="token operator">=canvasElement<跨度class="token punctuation">.<跨度class="token method function property-access">getContext<跨度class="token punctuation">(<跨度class="token string">“二维”<跨度class="token punctuation">)<跨度class="token punctuation">;<跨度class="token keyword">常量qrResult<跨度class="token operator">=<跨度class="token dom variable">文档<跨度class="token punctuation">.<跨度class="token method function property-access">getElementById<跨度class="token punctuation">(<跨度class="token string">“qr-result”<跨度class="token punctuation">)<跨度class="token punctuation">;<跨度class="token keyword">常量outputData<跨度class="token operator">=<跨度class="token dom variable">文档<跨度class="token punctuation">.<跨度class="token method function property-access">getElementById<跨度class="token punctuation">(<跨度class="token string">“outputData”<跨度class="token punctuation">)<跨度class="token punctuation">;<跨度class="token keyword">常量btnScanQR<跨度class="token operator">=<跨度class="token dom variable">文档<跨度class="token punctuation">.<跨度class="token method function property-access">getElementById<跨度class="token punctuation">(<跨度class="token string">“btn-scan-qr”<跨度class="token punctuation">)<跨度class="token punctuation">;<跨度class="token keyword">让扫描<跨度class="token operator">=<跨度class="token boolean">假<跨度class="token punctuation">;

在这段代码的顶部,我们得到qrcode对象的窗口为了方便,把它赋给一个常数。我们还创建了一个视频元素,我们将使用它来处理来自相机的图像。

然后我们得到帆布元素,我们用它来赋值2 d上下文到一个常数。我们需要这个来绘制来自相机的图像。

然后我们获得相关元素来显示结果并与应用程序交互,在底部,我们声明扫描变量,以保持扫描仪的状态。

接下来,我们将为QR码阅读器设置回调。在文件底部添加以下内容:

qrcode<跨度class="token punctuation">.<跨度class="token method-variable function-variable method function property-access">回调<跨度class="token operator">=<跨度class="token punctuation">(<跨度class="token parameter">res<跨度class="token punctuation">)<跨度class="token arrow operator">= ><跨度class="token punctuation">{<跨度class="token keyword control-flow">如果<跨度class="token punctuation">(res<跨度class="token punctuation">)<跨度class="token punctuation">{outputData<跨度class="token punctuation">.<跨度class="token property-access">innerText<跨度class="token operator">=res<跨度class="token punctuation">;扫描<跨度class="token operator">=<跨度class="token boolean">假<跨度class="token punctuation">;视频<跨度class="token punctuation">.<跨度class="token property-access">srcObject<跨度class="token punctuation">.<跨度class="token method function property-access">getTracks<跨度class="token punctuation">(<跨度class="token punctuation">)<跨度class="token punctuation">.<跨度class="token method function property-access">forEach<跨度class="token punctuation">(<跨度class="token parameter">跟踪<跨度class="token arrow operator">= ><跨度class="token punctuation">{跟踪<跨度class="token punctuation">.<跨度class="token method function property-access">停止<跨度class="token punctuation">(<跨度class="token punctuation">)<跨度class="token punctuation">;<跨度class="token punctuation">}<跨度class="token punctuation">)<跨度class="token punctuation">;qrResult<跨度class="token punctuation">.<跨度class="token property-access">隐藏的<跨度class="token operator">=<跨度class="token boolean">假<跨度class="token punctuation">;btnScanQR<跨度class="token punctuation">.<跨度class="token property-access">隐藏的<跨度class="token operator">=<跨度class="token boolean">假<跨度class="token punctuation">;canvasElement<跨度class="token punctuation">.<跨度class="token property-access">隐藏的<跨度class="token operator">=<跨度class="token boolean">真正的<跨度class="token punctuation">;<跨度class="token punctuation">}<跨度class="token punctuation">}<跨度class="token punctuation">;

这里我们赋值回调的功能qrcode对象。当图书馆检测到二维码时,它会调用这个功能。它提供res参数,包含扫描结果,所以我们把它赋值给innerText的属性outputData元素。

这里还有四件事。首先,我们设置扫描变量设为false,因为我们已经解码了二维码之后就不想再扫描了。

然后,我们就能从小溪里找到所有的痕迹srcObjec的属性视频元素,一个接一个地阻止他们。这就是我们停止播放用户相机的方法。

在那之后,我们确保我们显示qrResult元素和btnScanQR元素,以便用户可以看到结果并触发另一次扫描。最后,我们隐藏canvasElement,因为我们不再需要它了。

这就是我们处理扫描仪响应所需要的全部内容。

现在我们需要访问摄像机馈线并设置一个循环,以便在我们的画布中绘制每一帧的图像。我们还需要另一个循环,每x毫秒扫描QR码。

扫描每一帧会浪费资源,所以我们最好在一个单独的循环中处理它,这样我们就可以控制运行算法的频率。

我们会在onclick的处理程序btnScanQR元素:

btnScanQR<跨度class="token punctuation">.<跨度class="token method-variable function-variable method function property-access">onclick<跨度class="token operator">=<跨度class="token punctuation">(<跨度class="token punctuation">)<跨度class="token arrow operator">= ><跨度class="token dom variable">导航器<跨度class="token punctuation">.<跨度class="token property-access">mediaDevices<跨度class="token punctuation">.<跨度class="token method function property-access">getUserMedia<跨度class="token punctuation">(<跨度class="token punctuation">{视频<跨度class="token operator">:<跨度class="token punctuation">{facingMode<跨度class="token operator">:<跨度class="token string">“环境”<跨度class="token punctuation">}<跨度class="token punctuation">}<跨度class="token punctuation">)<跨度class="token punctuation">.<跨度class="token method function property-access">然后<跨度class="token punctuation">(<跨度class="token keyword">函数<跨度class="token punctuation">(<跨度class="token parameter">流<跨度class="token punctuation">)<跨度class="token punctuation">{扫描<跨度class="token operator">=<跨度class="token boolean">真正的<跨度class="token punctuation">;qrResult<跨度class="token punctuation">.<跨度class="token property-access">隐藏的<跨度class="token operator">=<跨度class="token boolean">真正的<跨度class="token punctuation">;btnScanQR<跨度class="token punctuation">.<跨度class="token property-access">隐藏的<跨度class="token operator">=<跨度class="token boolean">真正的<跨度class="token punctuation">;canvasElement<跨度class="token punctuation">.<跨度class="token property-access">隐藏的<跨度class="token operator">=<跨度class="token boolean">假<跨度class="token punctuation">;视频<跨度class="token punctuation">.<跨度class="token method function property-access">setAttribute<跨度class="token punctuation">(<跨度class="token string">“playsinline”<跨度class="token punctuation">,<跨度class="token boolean">真正的<跨度class="token punctuation">)<跨度class="token punctuation">;<跨度class="token comment">//需要告诉iOS safari我们不需要全屏视频<跨度class="token punctuation">.<跨度class="token property-access">srcObject<跨度class="token operator">=流<跨度class="token punctuation">;视频<跨度class="token punctuation">.<跨度class="token method function property-access">玩<跨度class="token punctuation">(<跨度class="token punctuation">)<跨度class="token punctuation">;<跨度class="token function">蜱虫<跨度class="token punctuation">(<跨度class="token punctuation">)<跨度class="token punctuation">;<跨度class="token function">扫描<跨度class="token punctuation">(<跨度class="token punctuation">)<跨度class="token punctuation">;<跨度class="token punctuation">}<跨度class="token punctuation">)<跨度class="token punctuation">;<跨度class="token punctuation">}<跨度class="token punctuation">;

好,我们来看看。我们调用<一个href="https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia">getUserMedia函数从mediaDevices对象的一部分<一个href="https://developer.mozilla.org/en-US/docs/Web/API/Navigator">导航器对象。这将使浏览器请求用户允许使用他们的相机。

getUserMedia函数接受一个对象作为参数,我们将视频对象与facingMode设置为“环境”.如果用户使用的是移动设备,这将尝试将摄像头放在背面。返回一个promise,解析后提供一个流,我们可以将该流分配给srcObject视频元素。然后我们设置“playsinline”属性来真正的,这将防止iOS safari进入全屏。

在这一点上,我们可以打()当然,这还不够。我们需要每帧都绘制流,所以我们调用蜱虫函数,然后扫描函数触发算法。

让我们定义蜱虫功能:

函数<跨度class="token function">蜱虫<跨度class="token punctuation">(<跨度class="token punctuation">)<跨度class="token punctuation">{canvasElement<跨度class="token punctuation">.<跨度class="token property-access">高度<跨度class="token operator">=视频<跨度class="token punctuation">.<跨度class="token property-access">videoHeight<跨度class="token punctuation">;canvasElement<跨度class="token punctuation">.<跨度class="token property-access">宽度<跨度class="token operator">=视频<跨度class="token punctuation">.<跨度class="token property-access">videoWidth<跨度class="token punctuation">;帆布<跨度class="token punctuation">.<跨度class="token method function property-access">drawImage<跨度class="token punctuation">(视频<跨度class="token punctuation">,<跨度class="token number">0<跨度class="token punctuation">,<跨度class="token number">0<跨度class="token punctuation">,canvasElement<跨度class="token punctuation">.<跨度class="token property-access">宽度<跨度class="token punctuation">,canvasElement<跨度class="token punctuation">.<跨度class="token property-access">高度<跨度class="token punctuation">)<跨度class="token punctuation">;扫描<跨度class="token operator">& &<跨度class="token function">requestAnimationFrame<跨度class="token punctuation">(蜱虫<跨度class="token punctuation">)<跨度class="token punctuation">;<跨度class="token punctuation">}

这是一个经典的逐帧循环。我们设置了高度和宽度canvasElement视频.然后我们画视频帆布在底部我们使用requestAnimationFrame然后传入蜱虫函数,以便在浏览器绘制下一帧时再次调用它。这是有条件的扫描变量是真正的

现在让我们定义扫描函数:

函数<跨度class="token function">扫描<跨度class="token punctuation">(<跨度class="token punctuation">)<跨度class="token punctuation">{<跨度class="token keyword control-flow">试一试<跨度class="token punctuation">{qrcode<跨度class="token punctuation">.<跨度class="token method function property-access">解码<跨度class="token punctuation">(<跨度class="token punctuation">)<跨度class="token punctuation">;<跨度class="token punctuation">}<跨度class="token keyword control-flow">抓<跨度class="token punctuation">(e<跨度class="token punctuation">)<跨度class="token punctuation">{<跨度class="token function">setTimeout<跨度class="token punctuation">(扫描<跨度class="token punctuation">,<跨度class="token number">300<跨度class="token punctuation">)<跨度class="token punctuation">;<跨度class="token punctuation">}<跨度class="token punctuation">}

这很简单。我们运行解码函数从qrcode库,它将寻找一个帆布ID为“qr-canvas”并扫描其内容。如果我们找不到任何东西,我们定义的错误将被捕获,我们将调用asetTimeout扫描时间为300毫秒。您可以将此设置为其他内容,看看会发生什么。你等下次扫描的时间越长,速度就越慢。等待的时间越短,你对用户设备的要求就越多,所以要注意。试着寻找一个最佳点。

这就是我们需要的!现在让我们试试这个应用程序。

看到QR码阅读器在行动

下面是代码和框中的工作项目.点击二维码按钮,并向相机显示一些二维码进行扫描。保持它的位置一会儿,你就会得到你的结果。你会惊讶于它的速度和流畅。

结论

所以我们有了它,你自己的手机网站的QR码阅读器。你也可以在任何平台上使用它,这使得它非常动态,并为你的客户带来很多价值。

QR码已经出现很多年了,由ZXing编写的图像处理代码大约在9年前首次移植到JavaScript。它经受住了时间的考验,如果不是的话,它仍然是最快的之一最快——网络的选择。它也是免费的开源软件,这让它变得更好。

我们希望你能想出一些惊人的东西!

可下载的资产

Baidu