做者:孫輝,美團金融前端團隊成員。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.
最後,團隊爲了招聘方便,整了個公衆號,主要是一些招聘信息,團隊信息,全部的技術文章在公衆號裏也能夠看到,對了,若是你想去美團其餘團隊,咱們也能夠幫你內推哦 ~
參考: