本篇文章給大家分享的是有關(guān)怎么利用小程序的canvas來繪制二維碼,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對(duì)這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡(jiǎn)單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名與空間、虛擬主機(jī)、營(yíng)銷軟件、網(wǎng)站建設(shè)、大通網(wǎng)站維護(hù)、網(wǎng)站推廣。
在微信小程序的業(yè)務(wù)中會(huì)有一些需要展示二維碼的場(chǎng)景。靜態(tài)二維碼可以直接存放在本地,使用圖片方式展示,但不適合根據(jù)用戶相關(guān)信息生成動(dòng)態(tài)的二維碼。下面將介紹下利用小程序的canvas能力繪制二維碼。
wx-qr
直接生成1.1 DEMO
微信開發(fā)者工具打開查看
# 通過 npm 安裝
1.2 安裝
npm i wx-qr -S # 通過 yarn 安裝 yarn add wx-qr
1.3 使用組件
首先在你所開發(fā)的小程序根目錄 app.json
或需要使用該組件的 xxx.json
中引用組件
(注意:請(qǐng)不要將組件命名為 wx-xxx
開頭,可能會(huì)導(dǎo)致微信小程序解析 tag 失敗 )
{ "usingComponents": { "qr-container": "wx-qr" } }
之后就可以在 wxml
中直接使用組件
Page({ data: { qrTxt: 'https://github.com/liuxdi/wx-qr', }, });
當(dāng)然,還可以支持很多種配置,詳見github 或者 碼云文檔。
2.0 二維碼的組成部分
定位圖案
Position Detection Pattern是定位圖案,用于標(biāo)記二維碼的矩形大小。這三個(gè)定位圖案有白邊叫Separators for Postion Detection Patterns。之所以三個(gè)而不是四個(gè)意思就是三個(gè)就可以標(biāo)識(shí)一個(gè)矩形了。
Timing Patterns也是用于定位的。原因是二維碼有40種尺寸,尺寸過大了后需要有根標(biāo)準(zhǔn)線,不然掃描的時(shí)候可能會(huì)掃歪了。
Alignment Patterns 只有Version 2以上(包括Version2)的二維碼需要這個(gè)東東,同樣是為了定位用的。
功能性數(shù)據(jù)
Format Information 存在于所有的尺寸中,用于存放一些格式化數(shù)據(jù)的。
Version Information 在 >= Version 7以上,需要預(yù)留兩塊3 x 6的區(qū)域存放一些版本信息。
數(shù)據(jù)碼和糾錯(cuò)碼
除了上述的那些地方,剩下的地方存放 Data Code 數(shù)據(jù)碼 和 Error Correction Code 糾錯(cuò)碼。
2.1 引入二維碼數(shù)據(jù)生成庫(kù)
復(fù)制qrcode.js至你的小程序相應(yīng)目錄。
2.2 小程序中建立canvas標(biāo)簽,并給canvas設(shè)置長(zhǎng)寬
2.3獲取canvas實(shí)例及上下文
const query = this.createSelectorQuery(); let dpr = wx.getSystemInfoSync().pixelRatio; query.select('#qr').fields({ node: true, size: true, id: true }) .exec((res) => { let { node: canvas, height, width } = res[0]; let ctx = canvas.getContext('2d'); canvas.width = width * dpr canvas.height = height * dpr ctx.scale(dpr, dpr); })
2.4 定義一些變量及繪制二維碼的數(shù)據(jù)碼區(qū)
其中QRCodeModel是從qrCode.js中導(dǎo)入的
// 二維碼的顏色 const colorDark = '#000'; // 獲取二維碼的大小,因css設(shè)置的為750rpx,將其轉(zhuǎn)為px const rawViewportSize = getPxFromRpx(750); // 二維碼容錯(cuò)率{ L: 1, M: 0, Q: 3, H: 2 } const correctLevel = 0; // 創(chuàng)建二維碼實(shí)例對(duì)象,并添加數(shù)據(jù)進(jìn)行生成 const qrCode = new QRCodeModel(-1, correctLevel); qrCode.addData(url); qrCode.make(); // 每個(gè)方向的二維碼數(shù)量 const nCount = qrCode.moduleCount; // 計(jì)算每個(gè)二維碼方塊的大小 const nSize = getRoundNum(rawViewportSize / nCount, 3) // 每塊二維碼點(diǎn)的大小比例 const dataScale = 1; // 計(jì)算出dataScale不為1時(shí),每個(gè)點(diǎn)的偏移值 const dataXyOffset = (1 - dataScale) * 0.5; // 循環(huán)行列繪制數(shù)據(jù)碼區(qū) for (let row = 0; row < nCount; row++) { for (let col = 0; col < nCount; col++) { // row 和 col 處的模塊是否是黑色區(qū) const bIsDark = qrCode.isDark(row, col); // 是否是二維碼的圖案定位標(biāo)識(shí)區(qū) Position Detection Pattern(如本模塊,是三個(gè)頂點(diǎn)位置處的大方塊) const isBlkPosCtr = (col < 8 && (row < 8 || row >= nCount - 8)) || (col >= nCount - 8 && row < 8); // 是否是Timing Patterns,也是用于協(xié)助定位掃描的 const isTiming = (row == 6 && col >= 8 && col <= nCount - 8) || (col == 6 && row >= 8 && row <= nCount - 8); // 如果是這些區(qū)域 則不進(jìn)行繪制 let isProtected = isBlkPosCtr || isTiming; // 計(jì)算每個(gè)點(diǎn)的繪制位置(left,top) const nLeft = col * nSize + (isProtected ? 0 : dataXyOffset * nSize); const nTop = row * nSize + (isProtected ? 0 : dataXyOffset * nSize); // 描邊色、線寬、填充色配置 ctx.strokeStyle = colorDark; ctx.lineWidth = 0.5; ctx.fillStyle = bIsDark ? colorDark : "rgba(255, 255, 255, 0.6)"; // 如果不是標(biāo)識(shí)區(qū),則進(jìn)行繪制 if (!isProtected) { ctx.fillRect( nLeft, nTop, (isProtected ? (isBlkPosCtr ? 1 : 1) : dataScale) * nSize, (isProtected ? (isBlkPosCtr ? 1 : 1) : dataScale) * nSize ); } } }
此時(shí)已經(jīng)繪制出二維碼的數(shù)據(jù)碼區(qū):
2.5 繪制圖形識(shí)別區(qū)
// 繪制Position Detection Pattern ctx.fillStyle = colorDark; ctx.fillRect(0, 0, 7 * nSize, nSize); ctx.fillRect((nCount - 7) * nSize, 0, 7 * nSize, nSize); ctx.fillRect(0, 6 * nSize, 7 * nSize, nSize); ctx.fillRect((nCount - 7) * nSize, 6 * nSize, 7 * nSize, nSize); ctx.fillRect(0, (nCount - 7) * nSize, 7 * nSize, nSize); ctx.fillRect(0, (nCount - 7 + 6) * nSize, 7 * nSize, nSize); ctx.fillRect(0, 0, nSize, 7 * nSize); ctx.fillRect(6 * nSize, 0, nSize, 7 * nSize); ctx.fillRect((nCount - 7) * nSize, 0, nSize, 7 * nSize); ctx.fillRect((nCount - 7 + 6) * nSize, 0, nSize, 7 * nSize); ctx.fillRect(0, (nCount - 7) * nSize, nSize, 7 * nSize); ctx.fillRect(6 * nSize, (nCount - 7) * nSize, nSize, 7 * nSize); ctx.fillRect(2 * nSize, 2 * nSize, 3 * nSize, 3 * nSize); ctx.fillRect((nCount - 7 + 2) * nSize, 2 * nSize, 3 * nSize, 3 * nSize); ctx.fillRect(2 * nSize, (nCount - 7 + 2) * nSize, 3 * nSize, 3 * nSize); // 繪制Position Detection Pattern 完畢 // 繪制Timing Patterns const timingScale = 1; const timingXyOffset = (1 - timingScale) * 0.5; for (let i = 0; i < nCount - 8; i += 2) { _drawDot(ctx, 8 + i, 6, nSize, timingXyOffset, timingScale); _drawDot(ctx, 6, 8 + i, nSize, timingXyOffset, timingScale); } // 繪制Timing Patterns 完畢
這時(shí)候,一個(gè)樸素的二維碼就繪制成功啦~
以上就是怎么利用小程序的canvas來繪制二維碼,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見到或用到的。希望你能通過這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。