微信小程序 -- 网址二维码生成器

3,171 阅读2分钟

微信小程序联盟上有一个小练习,是要实现小程序上的二维码生成器,想想基于jquery的二维码生成插件有很多,但是小程序是不允许操作dom的,所以自己找了一个纯javascript版的二维码生成源码,然后换汤不换药把其中的hmtl5中的canvas改为小程序的canvas;

效果图

纯javascript版js源码:

qrcode

1、解读源码,修改绘制canvas部分,源代码如下

draw: function (string, canvas, size, ecc) {
            
            ecclevel = ecc || ecclevel;
            canvas = canvas || _canvas;

            if (!canvas) {
                console.warn('No canvas provided to draw QR code in!')
                return;
            }

            size = size || _size || Math.min(canvas.width, canvas.height);

            var frame = genframe(string),
                ctx = canvas.getContext('2d'),
                px = Math.round(size / (width + 8));

            var roundedSize = px * (width + 8),
                offset = Math.floor((size - roundedSize) / 2);

            size = roundedSize;

            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.fillStyle = '#fff';
            ctx.fillRect(0, 0, size, size);
            ctx.fillStyle = '#000';
            for (var i = 0; i < width; i++) {
                for (var j = 0; j < width; j++) {
                    if (frame[j * width + i]) {
                        ctx.fillRect(px * (4 + i) + offset, px * (4 + j) + offset, px, px);
                    }
                }
            }

        },

2、然后愉快的将代码修改如下:

draw: function (string, canvas, cavW, cavH, ecc) {
            ecclevel = ecc || ecclevel;
            canvas = canvas || _canvas;
            if (!canvas) {
                console.warn('No canvas provided to draw QR code in!')
                return;
            }

            var size =  Math.min(cavW, cavH);

            var frame = this.getFrame(string),
                ctx = wx.createContext(),
                px = Math.round(size / (width + 8));

            var roundedSize = px * (width + 8),
                offset = Math.floor((size - roundedSize) / 2);
            size = roundedSize;
            ctx.clearRect(0, 0, cavW, cavW);
            // ctx.setFillStyle('#ffffff');
            // ctx.rect(0, 0, size, size);
            ctx.setFillStyle('#000000');
			// ctx.setLineWidth(1);
            for (var i = 0; i < width; i++) {
                for (var j = 0; j < width; j++) {
                    if (frame[j * width + i]) {
                        ctx.fillRect(px * (4 + i) + offset, px * (4 + j) + offset, px, px);
					}
                }
            }
           
			wx.drawCanvas({
          		canvasId: canvas,
          		actions: ctx.getActions()
    		});
        }
    }

3、哈哈,愉快的运行起来~~~~~~报错!!

赶紧看看小程序的api,发现小程序是没有fillRect()方法的,只有rect()方法,所以啪~啪~啪改为如下:

 for (var i = 0; i < width; i++) {
                for (var j = 0; j < width; j++) {
                    if (frame[j * width + i]) {   
                        ctx.rect(px * (4 + i) + offset, px * (4 + j) + offset, px, px);
					}
                }
            }

运行,懵逼了,怎么没有二维码呢,我的二维码呢?好吧接着分析rect语fillRect的区别,其实rect方法只是绘制出轮廓,并不会对路径进行填充,所以紧接其后要对其fill填充。

把代码改为如下:

ctx.setFillStyle('#000000');
			// ctx.setLineWidth(1);
            for (var i = 0; i < width; i++) {
                for (var j = 0; j < width; j++) {
                    if (frame[j * width + i]) {   
                        ctx.rect(px * (4 + i) + offset, px * (4 + j) + offset, px, px);
                        ctx.fill();
                    }
                }
            }

运行~~~噢啦,终于出现期待已久的二维码喽!!


好了,总算完成了,但是怎么生成二维码的时候感觉有点慢呢,于是借用同事的手机(安卓系统)试了一下,输入网址,点击生成~~

崩了,微信直接挂了,好吧接着找原因,感觉影响速度的只能是for循环那块代码,于是把ctx.fill()拿到for最外层;

 for (var i = 0; i < width; i++) {
                for (var j = 0; j < width; j++) {
                    if (frame[j * width + i]) {   
                        ctx.rect(px * (4 + i) + offset, px * (4 + j) + offset, px, px);
                        // ctx.fill();
                    }
                }
            }
            ctx.fill();

运行~~这速度,飞快!自己的小7也不卡了,又用同事的试了一把,没问题。原来对绘制路径填充只需要最后填充就Ok了,我还二逼的对每次绘制进行了填充。

最新完整代码地址:小程序二维码生成器