diff --git a/src/qrcode.js b/src/qrcode.js index eda2233..e550507 100644 --- a/src/qrcode.js +++ b/src/qrcode.js @@ -1,6 +1,54 @@ var $ = require('jquery'); var QRCodeAlg = require('./qrcodealg'); var qrcodeAlgObjCache = []; +/** +* 预载图片 +*/ +var loadImage = function(url,callback){ + var img = new Image(); + img.src = url; + img.onload = function () { + callback(this); + img.onload = null + }; +} +/** +* 计算矩阵点的前景色 +* @param {Obj} config +* @param {Number} config.row 点x坐标 +* @param {Number} config.col 点y坐标 +* @param {Number} config.count 矩阵大小 +* @param {Number} config.options 组件的options +* @return {String} +*/ +var getForeGround = function(config){ + var options = config.options; + if( options.pdground && ( + (config.row > 1 && config.row < 5 && config.col >1 && config.col<5) + || (config.row > (config.count - 6) && config.row < (config.count - 2) && config.col >1 && config.col<5) + || (config.row > 1 && config.row < 5 && config.col > (config.count - 6) && config.col < (config.count - 2)) + )){ + return options.pdground; + } + return options.foreground; +} +/** +* 点是否在Position Detection +* @param {row} 矩阵行 +* @param {col} 矩阵列 +* @param {count} 矩阵大小 +* @return {Boolean} +*/ +var inPositionDetection = function(row, col, count){ + if( + (row<7 && col<7) + || (row > (count - 8) && col < 7) + || (row < 7 && col >(count - 8) ) + ){ + return true; + } + return false; +} /** * 二维码构造函数,主要用于绘制 @@ -21,7 +69,10 @@ var qrcode = function(opt) { height: 256, correctLevel: 3, background: "#ffffff", - foreground: "#000000" + foreground: "#000000", + image : '', + imageWidth: 30, + imageHeight: 30 }, opt); //使用QRCodeAlg创建二维码结构 @@ -32,6 +83,7 @@ var qrcode = function(opt) { break; } } + if(i == l){ qrCodeAlg = new QRCodeAlg(this.options.text, this.options.correctLevel); qrcodeAlgObjCache.push({text:this.options.text, correctLevel: this.options.correctLevel, obj:qrCodeAlg}); @@ -67,24 +119,39 @@ qrcode.prototype.createDefault = function(qrCodeAlg) { }; qrcode.prototype.createCanvas = function(qrCodeAlg) { //创建canvas节点 + var that = this; var canvas = document.createElement('canvas'); - canvas.width = this.options.width; - canvas.height = this.options.height; + canvas.width = that.options.width; + canvas.height = that.options.height; var ctx = canvas.getContext('2d'); + var count = qrCodeAlg.getModuleCount(); //计算每个点的长宽 - var tileW = (this.options.width / qrCodeAlg.getModuleCount()).toPrecision(4); - var tileH = this.options.height / qrCodeAlg.getModuleCount().toPrecision(4); - - //绘制 - for (var row = 0; row < qrCodeAlg.getModuleCount(); row++) { - for (var col = 0; col < qrCodeAlg.getModuleCount(); col++) { - ctx.fillStyle = qrCodeAlg.modules[row][ col] ? this.options.foreground : this.options.background; - var w = (Math.ceil((col + 1) * tileW) - Math.floor(col * tileW)); - var h = (Math.ceil((row + 1) * tileW) - Math.floor(row * tileW)); - ctx.fillRect(Math.round(col * tileW), Math.round(row * tileH), w, h); + var tileW = (that.options.width / count).toPrecision(4); + var tileH = (that.options.height / count).toPrecision(4); + //绘制 + + for (var row = 0; row < count; row++) { + for (var col = 0; col < count; col++) { + var w = (Math.ceil((col + 1) * tileW) - Math.floor(col * tileW)); + var h = (Math.ceil((row + 1) * tileW) - Math.floor(row * tileW)); + var foreground = getForeGround({ + row : row, + col : col, + count : count, + options : that.options + }); + ctx.fillStyle = qrCodeAlg.modules[row][col] ? foreground : that.options.background; + ctx.fillRect(Math.round(col * tileW), Math.round(row * tileH), w, h); } } + if(that.options.image){ + loadImage(that.options.image, function(img){ + var x = ((that.options.width - that.options.imageWidth)/2).toFixed(2); + var y = ((that.options.height - that.options.imageHeight)/2).toFixed(2); + ctx.drawImage(img, x, y, that.options.imageWidth, that.options.imageHeight); + }); + } //返回绘制的节点 return canvas; }; @@ -93,45 +160,61 @@ qrcode.prototype.createCanvas = function(qrCodeAlg) { * @return {} */ qrcode.prototype.createTable = function(qrCodeAlg) { - //创建table节点 - var s = []; - s.push(''); + var count = qrCodeAlg.getModuleCount(); + // 计算每个节点的长宽;取整,防止点之间出现分离 - var tileW = -1, tileH = -1, caculateW = -1, caculateH = -1; - tileW = caculateW = Math.floor(this.options.width / qrCodeAlg.getModuleCount()); - tileH = caculateH = Math.floor(this.options.height / qrCodeAlg.getModuleCount()); - if(caculateW <= 0){ - if(qrCodeAlg.getModuleCount() < 80){ - tileW = 2; - } else { - tileW = 1; - } + var tileW = Math.floor(this.options.width / count); + var tileH = Math.floor(this.options.height / count); + if(tileW <= 0){ + tileW = count < 80 ? 2 : 1; } - if(caculateH <= 0){ - if(qrCodeAlg.getModuleCount() < 80){ - tileH = 2; - } else { - tileH = 1; - } + if(tileH <= 0){ + tileH = count < 80 ? 2 : 1; } + //创建table节点 + //重算码大小 + var s = []; + s.push('
'); + // 绘制二维码 - foreTd = '', - backTd = '', - l = qrCodeAlg.getModuleCount(); + var backTd = ''; - for (var row = 0; row < l; row++) { + for (var row = 0; row < count; row++) { s.push(''); - for (var col = 0; col < l; col++) { - s.push(qrCodeAlg.modules[row][col] ? foreTd : backTd); + for (var col = 0; col < count; col++) { + var foreground = getForeGround({ + row : row, + col : col, + count : count, + options : this.options + }); + s.push(qrCodeAlg.modules[row][col] ? '' : backTd); } s.push(''); } s.push('
'); + + if(this.options.image){ + // 计算表格的总大小 + var width = tileW * count; + var height = tileH * count; + var x = ((width - this.options.imageWidth)/2).toFixed(2); + var y = ((height - this.options.imageHeight)/2).toFixed(2); + s.unshift('
'); + s.push(''); + s.push('
'); + } + var span = document.createElement("span"); - span.innerHTML=s.join(''); + span.innerHTML=s.join(''); return span.firstChild; }; @@ -142,20 +225,26 @@ qrcode.prototype.createTable = function(qrCodeAlg) { */ qrcode.prototype.createSVG = function (qrCodeAlg){ var x, dx, y, dy, - moduleCount = qrCodeAlg.getModuleCount(), - scale = this.options.height / this.options.width, - svg = '', + + 'viewbox="0 0 ' + count * 10 + ' ' + count * 10 * scale + '">', rectHead = '', backRect = ' style="stroke-width:0.5;stroke:' + this.options.background + ';fill:' + this.options.background + ';">'; // draw in the svg - for (var row = 0; row < moduleCount; row++) { - for (var col = 0; col < moduleCount; col++) { + for (var row = 0; row < count; row++) { + for (var col = 0; col < count; col++) { + var foreground = getForeGround({ + row : row, + col : col, + count : count, + options : this.options + }); + var foreRect = ' style="stroke-width:0.5;stroke:' + foreground + + ';fill:' + foreground + ';">'; x = col * 10; y = row * 10 * scale; dx = (col + 1) * 10; @@ -171,6 +260,12 @@ qrcode.prototype.createSVG = function (qrCodeAlg){ } } + if(this.options.image){ + var x = ((this.options.width - this.options.imageWidth)/2).toFixed(2); + var y = ((this.options.height - this.options.imageHeight)/2).toFixed(2); + svg += ''; + } + svg += ''; // return just built svg