做者:孙辉,美团金融前端团队成员。15年毕业加入美团,相信技术,更相信技术只是大千世界里知识的一种,我的博客: sunyuhui.comhtml
最近这段时间,团队在作的业务主要和二维码相关,在作的过程当中,发现不论是本身仍是团队里其余同窗,都对二维码自己了解甚少,所以本身调研了一番,在团队内部作了一次分享,在这里整理出来。前端
有意思的是以前在作业务时,QA跑过来问我一个问题:jquery
我两次进入同一个页面,发现图片不同,是否是有问题啊?git
我当时很庆幸本身在作项目以前了解了一些二维码相关的东西,因此我问他:github
你两次扫码的结果是同样的吗?shell
备注:本文涉及到的二维码原理相对粗浅,只能当作二维码的科普文,如有心对二维码生成和扫码原理有深刻研究,请出门左转~canvas
为了让你们先直观了解二维码的结构,建议你们先去QR Code Generater,在左侧的地址栏里持续输入不一样的内容(随便敲,使劲敲),在二维码图片的变动过程当中,仔细观察图片,看图片的变化是否是有什么规律。bash
这时候你内心应该大体有谱了,二维码对你来讲再也不只是混沌的黑白图片,如今咱们来介绍下二维码的结构微信
总体分为功能区和编码区,功能区主要用于定位
,编码区则是真正存储数据
的。函数
有几个地方须要注意:
那上面的二维码究竟是怎么一步步生成的呢?
上面的图中,详细标注出了二维码的各个结构生成的顺序。左边的流程图是绘制的顺序,右边的图表示绘制到这个流程时已经绘制出来的图形。好比,绘制到【定位图形】这一步时,整个二维码就已经有了左上角、右上角、左小角、链接这三者的横竖两条定位标志以及右下方的校订标志
到添加【掩码图案】这个阶段时,整个二维码其实已经绘制完成了,可是若是只是按照实际的信息来绘制,可能会致使页面上有一大片黑色或者一大片白色,而不是咱们如今看到的黑白交叉的图形,这样会致使扫码时识别困难。因此在这一步会再作一步操做:从已有的模板中(模板的黑白是交叉的)选一个,来和生成的二维码图形作异或操做,其中异或操做就是JavaScript中的^运算符
。
其实在整个生成过程当中,我最好奇的是这些黑白色是怎么生成的(恩,我相信你也是这样的 ^-^ )。
如今咱们以 jquery-qrcode 为例,看下源码
options = $.extend( {}, {
render : "canvas",
width : 256,
height : 256,
typeNumber : -1,
correctLevel : QRErrorCorrectLevel.H,
background : "#ffffff",
foreground : "#000000"
}, options);复制代码
这里是生成二维码时的一些参数,能够看到参数里有个background
属性和foreground
属性,分别为白色和黑色,咦?这么巧?
继续看
// draw in the canvas
for( var row = 0; row < qrcode.getModuleCount(); row++ ){
for( var col = 0; col < qrcode.getModuleCount(); col++ ){
ctx.fillStyle = qrcode.isDark(row, col) ? options.foreground : 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);
}
}复制代码
这里就是二层循环,用来绘制二维码的内容(二维码是矩形,因此两层循环),其中有行代码鹤立鸡群,立马引发了个人注意:
ctx.fillStyle = qrcode.isDark(row, col) ? options.foreground : options.background;
isDark
函数是干啥的?咱们去 源码 瞅瞅,而后就能发现,这个函数其实返回的就是二维码里这个位置上的二进制数据,从 这篇文章 里咱们知道二维码生成过程当中,会把全部信息都转换成二进制,因此二维码内容上的数据不是0
就是1
,那么在isDark
函数里,咱们发现,若是位置上的数据是1
,就使用白色,若是数据是0
,就使用黑色。
恩, 这时候就知道为啥二维码是黑白的了吧。
源码在手,天下我有
因此让咱们来尝试着生成彩色的二维码吧!
咱们把生成二维码的foreground
参数和background
参数修改一下,
options = $.extend( {}, {
render : "canvas",
width : 256,
height : 256,
typeNumber : -1,
correctLevel : QRErrorCorrectLevel.H,
background : "#f00", //改为红色
foreground : "#0f0" //改为绿色
}, options);
恩,是的,咱们生成了一个大红大绿的二维码。。。。。绿色对应原来的白色,红色对应原来的黑色。(我打赌,你以前确定没有见过这么艳的二维码 ~
不是相同的,就如同咱们开篇QA提到的那样,不过扫码后获得的结果是同样的。不一样的缘由是因为在具体生成黑白块时,是按照必定规律随机放置在图片中的。
嗯,好问题,这个问题咱们稍后解答~
你们日常在用各类APP扫码的时候,主要是付款、取(电影)票、添加微信好友等一些场景
咱们能明显感觉到的只是那呲的一声,那么在扫码的时候究竟发生了什么呢?我最近在作的业务中就有一环是【扫码】,因此我研究了一下。总体流程图是这样的
总的来讲,扫码的流程就是两步:
这时候你再回想下本身在微信、美团、点评等APP里使用扫码功能时出现的不一样状况,恩,你应该明白了。。
也许你已经习惯了每次扫码都会跳转到一个新页面,又或者你日常根本没注意这种事,但并不老是 扫码后跳转到一个连接 这么简单,而是对扫码返回的信息作不一样处理。跳转到一个连接 只是其中一种方式。
在生成二维码时,咱们提过到,二维码的生成过程,就是一个对信息加密的过程,那么【扫码】这个过程呢?其实就是一个解密的过程。具体怎么去解密的,能够去读一下Zxing的源码。
其实都是调用的手机的摄像头,可是扫码的摄像头由APP控制,具有解析二维码内容的能力。
即使是从颜值上考虑,彩色的也会更好看,在现在颜值即正义的时代里,不可能有人想不到用彩色的二维码来代替黑白的。
缘由是因为:黑白二维码扫码速度更快,对于手机摄像头来讲,要读取信息,就要获取图片中的两种二进制信息(1和0),在前文已经说过,1表明白色,0表明黑色,黑色的色值是#000000,白色的色值是#ffffff,在全部颜色中,只有黑色和白色的色值差是最大的,对手机来讲,也就更容易区分了,可是若是咱们用其余的两种颜色来代替黑色和白色呢?其实我已经在前文里把彩色二维码给你们展示了,你们能够分别扫一下彩色的二维码和黑白的二维码,应该能明显感受到黑白的更快。
这个问题多是不少作二维码相关业务的人关注的事情了,因素也有多方面的。
从二维码的角度:
从手机的角度
其中二维码的平整度(二维码都放在一个壳子里)
这个因素,你们日常在外面吃东西扫二维码付款时,应该均可以看到二维码是放在一个白色的壳子里,我不知道这是否是各大公司有意识的作这件事,也许他们只是想延长二维码的使用寿命,但这个措施确实作的很是好。
ok,到这里就差很少了,但愿看完这篇文章以后,你们对二维码应该有了一些了解,不会像之前同样,二维码对你们来讲只是一张黑白图片。
Done.
最后,团队为了招聘方便,整了个公众号,主要是一些招聘信息,团队信息,全部的技术文章在公众号里也能够看到,对了,若是你想去美团其余团队,咱们也能够帮你内推哦 ~
参考: