@roronoalee/qrcodejs
v1.0.1
Published
QRCode.js is javascript library for making QRCode. QRCode.js supports Cross-browser with HTML5 Canvas and table tag in DOM. QRCode.js has no dependencies.
Downloads
5
Readme
QRCode.js
QRCode.js is javascript library for making QRCode. QRCode.js supports Cross-browser with HTML5 Canvas and table tag in DOM. QRCode.js has no dependencies.
Basic Usages
<div id="qrcode"></div>
<script type="text/javascript">
new QRCode(document.getElementById("qrcode"), "http://jindo.dev.naver.com/collie");
</script>
or with some options
<div id="qrcode"></div>
<script type="text/javascript">
var qrcode = new QRCode(document.getElementById("qrcode"), {
text: "http://jindo.dev.naver.com/collie",
width: 128,
height: 128,
colorDark : "#000000",
colorLight : "#ffffff",
correctLevel : QRCode.CorrectLevel.H,
done: function () {
console.log('draw done');
},
fail: function (err) {
console.log('draw fail', err);
}
});
</script>
and you can use some methods
qrcode.clear(); // clear the code.
qrcode.makeCode("http://naver.com"); // make another code.
modify
最近有一个需求,需要将连接转换为二维码。
直接找了github最多star的库 https://github.com/davidshimjs/qrcodejs。
在使用中遇到了一些小问题,并且这个库很久不维护了,加上遇到的问题网上并没有很好的解决方案,所以fork一下修改源码,方便个人后续使用。
problem
在使用问题中发现有下面的几个问题。
不支持模块化
虽然支持npm安装,但是没办法在项目中使用
在某些安卓机(小米)下二维码没有生成
二维码绘制结束或者报错没有提供api来进行通知
code
粗略地将源码看了一下,简单说明一下运行流程。
将实例化QRcode参数options.text使用qrcode算法转换为矩阵(就是一个二维数组)。
判断当前文件是否是svg文件,是则调用svg api绘制矩阵。不是则根据参数及浏览器支持情况选择绘制方案。
根据options.useSVG选择是否使用svg渲染,如果不是则看浏览器是否支持canvas,不支持则用table绘制。
如果使用canvas绘制矩阵,调用canvas.toDataUrl获得一个base64格式的图片,之后创建img标签插入实例化QRcode时传入参数的dom中。
resolve
- 将源码用umd包装
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define('QRCode', factory);
} else if (typeof module === 'object' && typeof exports === 'object') {
module.exports = factory();
} else {
root.QRCode = factory();
}
}(this, function () {
// ...code
return QRcode;
}));
这个不用说了,修改完代码自己推送一下npm喽~
当遇到二维码不生成这个问题的时候,当然是先百度谷歌一下喽,网上针对这个问题方案有 MutationObserve,setTimeout,甚至还有轮询检测等,基本都是基于观察dom中img的生成和img的src属性是否存在来解决。
比起问题是怎么解决的,我更想知道问题是怎么来的。
查看源码后发现是由于源码中_getAndroid获取版本信息的正则写的有问题,而导致QRCode.prototype.makeImage中本该执行的绘制方法没有执行。
QRCode.prototype.makeImage = function () {
// this._android 在有些安卓机型下为false
if (typeof this._oDrawing.makeImage == "function" && (!this._android || this._android >= 3)) {
this._oDrawing.makeImage();
}
};
function _getAndroid() {
var android = false;
var sAgent = navigator.userAgent;
if (/android/i.test(sAgent)) { // android
android = true;
var aMat = sAgent.toString().match(/android ([0-9]\.[0-9])/i);
if (aMat && aMat[1]) {
android = parseFloat(aMat[1]);
}
}
return android;
}
我们可以看到 这个安卓版本正则的获取是有问题的:
- ua版本必须有两位以上(国内很多安卓机型ua中 ua版本返回的是一位,看来国外友人并不了解国内的手机厂商啊~)
- 只能匹配10以下版本,并且版本第二位只能匹配一位(听说安卓10已经发布了 233333)
所以需要将正则改写为如下形式
/android (\d+(\.\d+)?)/i
- 绘制完成通知:可以在实例化QRcode时传入回调函数,然后根据各种渲染方案调用即可。
supplement
- 在测试时发现下面this._android会报错。
if (this._android && this._android <= 2.1) {
var factor = 1 / window.devicePixelRatio;
var drawImage = CanvasRenderingContext2D.prototype.drawImage;
CanvasRenderingContext2D.prototype.drawImage = function (image, sx, sy, sw, sh, dx, dy, dw, dh) {
if (("nodeName" in image) && /img/i.test(image.nodeName)) {
for (var i = arguments.length - 1; i >= 1; i--) {
arguments[i] = arguments[i] * factor;
}
} else if (typeof dw == "undefined") {
arguments[1] *= factor;
arguments[2] *= factor;
arguments[3] *= factor;
arguments[4] *= factor;
}
drawImage.apply(this, arguments);
};
}
在cmd中this指向undefined,而将QRcode挂载到window上或者使用amd时this指向则是window。
// 修改
var _android = _getAndroid();
if (_android && _android <= 2.1) {
// ...code
}
降级
虽然源码中做了多种方案,但是因为一些产品和视觉上的限制,可能绘制的二维码并不可用(依赖客户端识别二维码的实现),二维码本意是方便传播,我们自己的需求中查看了数据预估了一下,对一些低版本直接进行了url的展示让用户自己复制。
测试
源码中有很多关于系统版本的判断,可以使用chrome的调试工具去修改ua测试。
use
webpack
npm install @roronoalee/qrcodejs
import QRCode from '@roronoalee/qrcodejs'
amd
require(['QRCode'], function (QRcode) {
// ... your code
});
cdn
<script src="{{YOUR_CND_DOMAIN}}/qrcode.js"></script>
Browser Compatibility
IE6~10, Chrome, Firefox, Safari, Opera, Mobile Safari, Android, Windows Mobile, ETC.
License
MIT License
Contact
twitter @davidshimjs