js生成二维码
jquery.qrcode.js
可以快速使用页面生成二维码。但改项目有两个小问题:1.不支持中文;2.不支持二维码中间生成图片。
支持中文的jquery-qrcode
jquery.qrcode.js
默认不支持中文。这跟js的机制有关系,jquery-qrcode
这个库是采用 charCodeAt()
这个方式进行编码转换的,
而这个方法默认会获取它的 Unicode 编码,一般的解码器都是采用UTF-8, ISO-8859-1等方式,英文是没有问题,如果是中文,一般情况下Unicode是UTF-16实现,长度2位,而UTF-8编码是3位,这样二维码的编解码就不匹配了。
jquery-qrcode GitHub源码地址 : https://github.com/jeromeetienne/jquery-qrcode
解决方式当然是,在二维码编码前把字符串转换成UTF-8,具体代码如下:
function qrcodeToUtf8(str) {
var out, i, len, c;
out = "";
len = str.length;
for (i = 0; i < len; i++) {
c = str.charCodeAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) {
out += str.charAt(i);
} else if (c > 0x07FF) {
out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
} else {
out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
}
}
return out;
}
支持带logo的二维码生成
增加qrcode的设置属性:
{
width : "220", //二维码的宽度
height : "220", //二维码的高度
imgWidth : 220/4, //图片宽
imgHeight : 220/4, //图片高
src: 'logo.png' //图片中央的二维码
}
生成二维码的时候会将src
地址中的图片放进标签中,覆盖到生成二位码的canvas中。
将中文转义和logo添加功能整合进jquery.qrcode.js
后代码如下(压缩版) :
function qrcodeToUtf8(str){var out,i,len,c;out="";len=str.length;for(i=0;i<len;i++){c=str.charCodeAt(i);if((c>=0x0001)&&(c<=0x007F)){out+=str.charAt(i);}else if(c>0x07FF){out+=String.fromCharCode(0xE0|((c>>12)&0x0F));out+=String.fromCharCode(0x80|((c>>6)&0x3F));out+=String.fromCharCode(0x80|((c>>0)&0x3F));}else{out+=String.fromCharCode(0xC0|((c>>6)&0x1F));out+=String.fromCharCode(0x80|((c>>0)&0x3F));}}return out;}function QR8bitByte(a){this.mode=QRMode.MODE_8BIT_BYTE,this.data=a}function QRCode(a,b){this.typeNumber=a,this.errorCorrectLevel=b,this.modules=null,this.moduleCount=0,this.dataCache=null,this.dataList=new Array()}function QRPolynomial(a,b){var c,d;if(void 0==a.length){throw new Error(a.length+"/"+b)}for(c=0;c<a.length&&0==a[c];){c++}for(this.num=new Array(a.length-c+b),d=0;d<a.length-c;d++){this.num[d]=a[d+c]}}function QRRSBlock(a,b){this.totalCount=a,this.dataCount=b}function QRBitBuffer(){this.buffer=new Array(),this.length=0}var QRMode,QRErrorCorrectLevel,QRMaskPattern,QRUtil,QRMath,i;for(function(a){a.fn.qrcode=function(b){var c,d;return"string"==typeof b&&(b={text:b}),b=a.extend({},{render:"canvas",256,height:256,imgWidth:b.width/4.7,imgHeight:b.height/4,typeNumber:-1,correctLevel:QRErrorCorrectLevel.H,background:"#ffffff",foreground:"#000000"},b),c=function(){var c,d,e,f,g,h,i,j,k,a=new QRCode(b.typeNumber,b.correctLevel);for(a.addData(qrcodeToUtf8(b.text)),a.make(),c=document.createElement("canvas"),c.width=b.width,c.height=b.height,d=c.getContext("2d"),b.src&&(e=new Image(),e.src=b.src,e.onload=function(){d.drawImage(e,(b.width-b.imgWidth)/2,(b.height-b.imgHeight)/2,b.imgWidth,b.imgHeight)}),f=b.width/a.getModuleCount(),g=b.height/a.getModuleCount(),h=0;h<a.getModuleCount();h++){for(i=0;i<a.getModuleCount();i++){d.fillStyle=a.isDark(h,i)?b.foreground:b.background,j=Math.ceil((i+1)*f)-Math.floor(i*f),k=Math.ceil((h+1)*f)-Math.floor(h*f),d.fillRect(Math.round(i*f),Math.round(h*g),j,k)}}return c},d=function(){var d,e,f,g,h,i,c=new QRCode(b.typeNumber,b.correctLevel);for(c.addData(qrcodeToUtf8(b.text)),c.make(),d=a("<table></table>").css("width",b.width+"px").css("height",b.height+"px").css("border","0px").css("border-collapse","collapse").css("background-color",b.background),e=b.width/c.getModuleCount(),f=b.height/c.getModuleCount(),g=0;g<c.getModuleCount();g++){for(h=a("<tr></tr>").css("height",f+"px").appendTo(d),i=0;i<c.getModuleCount();i++){a("<td></td>").css("width",e+"px").css("background-color",c.isDark(g,i)?b.foreground:b.background).appendTo(h)}}return d},this.each(function(){var e="canvas"==b.render?c():d();a(e).appendTo(this)})}}(jQuery),QR8bitByte.prototype={getLength:function(){return this.data.length},write:function(a){for(var b=0;b<this.data.length;b++){a.put(this.data.charCodeAt(b),8)}}},QRCode.prototype={addData:function(a){var b=new QR8bitByte(a);this.dataList.push(b),this.dataCache=null},isDark:function(a,b){if(0>a||this.moduleCount<=a||0>b||this.moduleCount<=b){throw new Error(a+","+b)}return this.modules[a][b]},getModuleCount:function(){return this.moduleCount},make:function(){var a,b,c,d,e,f;if(this.typeNumber<1){for(a=1,a=1;40>a;a++){for(b=QRRSBlock.getRSBlocks(a,this.errorCorrectLevel),c=new QRBitBuffer(),d=0,e=0;e<b.length;e++){d+=b[e].dataCount}for(e=0;e<this.dataList.length;e++){f=this.dataList[e],c.put(f.mode,4),c.put(f.getLength(),QRUtil.getLengthInBits(f.mode,a)),f.write(c)}if(c.getLengthInBits()<=8*d){break}}this.typeNumber=a}this.makeImpl(!1,this.getBestMaskPattern())},makeImpl:function(a,b){