溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎么利用小程序的canvas來繪制二維碼

發(fā)布時間:2022-01-06 12:51:33 來源:億速云 閱讀:625 作者:柒染 欄目:移動開發(fā)

本篇文章給大家分享的是有關(guān)怎么利用小程序的canvas來繪制二維碼,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

在微信小程序的業(yè)務(wù)中會有一些需要展示二維碼的場景。靜態(tài)二維碼可以直接存放在本地,使用圖片方式展示,但不適合根據(jù)用戶相關(guān)信息生成動態(tài)的二維碼。下面將介紹下利用小程序的canvas能力繪制二維碼。

1 方法一:通過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 中引用組件

(注意:請不要將組件命名為 wx-xxx 開頭,可能會導(dǎo)致微信小程序解析 tag 失敗 )

{
  "usingComponents": {
    "qr-container": "wx-qr"
  }
}

之后就可以在 wxml 中直接使用組件

<qr-container text="{{qrTxt}}" size="750"></qr-container>
Page({
    data: {
        qrTxt: 'https://github.com/liuxdi/wx-qr',
    },
});

當(dāng)然,還可以支持很多種配置,詳見github 或者 碼云文檔。

2. 方式二:基于QRCode.js結(jié)合canvas繪制

2.0 二維碼的組成部分

怎么利用小程序的canvas來繪制二維碼

定位圖案
  • Position Detection Pattern是定位圖案,用于標(biāo)記二維碼的矩形大小。這三個定位圖案有白邊叫Separators for Postion Detection Patterns。之所以三個而不是四個意思就是三個就可以標(biāo)識一個矩形了。

  • Timing Patterns也是用于定位的。原因是二維碼有40種尺寸,尺寸過大了后需要有根標(biāo)準(zhǔn)線,不然掃描的時候可能會掃歪了。

  • Alignment Patterns 只有Version 2以上(包括Version2)的二維碼需要這個東東,同樣是為了定位用的。

功能性數(shù)據(jù)
  • Format Information 存在于所有的尺寸中,用于存放一些格式化數(shù)據(jù)的。

  • Version Information 在 >= Version 7以上,需要預(yù)留兩塊3 x 6的區(qū)域存放一些版本信息。

數(shù)據(jù)碼和糾錯碼
  • 除了上述的那些地方,剩下的地方存放 Data Code 數(shù)據(jù)碼 和 Error Correction Code 糾錯碼。

2.1 引入二維碼數(shù)據(jù)生成庫

復(fù)制qrcode.js至你的小程序相應(yīng)目錄。

2.2 小程序中建立canvas標(biāo)簽,并給canvas設(shè)置長寬

<canvas id="qr" type="2d" style="height: 750rpx;width: 750rpx;"></canvas>

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);
// 二維碼容錯率{ L: 1, M: 0, Q: 3, H: 2 }
const correctLevel = 0;
// 創(chuàng)建二維碼實(shí)例對象,并添加數(shù)據(jù)進(jìn)行生成
const qrCode = new QRCodeModel(-1, correctLevel);
qrCode.addData(url);
qrCode.make();

// 每個方向的二維碼數(shù)量
const nCount = qrCode.moduleCount;
// 計算每個二維碼方塊的大小
const nSize = getRoundNum(rawViewportSize / nCount, 3)
// 每塊二維碼點(diǎn)的大小比例
const dataScale = 1;
// 計算出dataScale不為1時,每個點(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)識區(qū) Position Detection Pattern(如本模塊,是三個頂點(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;
    // 計算每個點(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)識區(qū),則進(jìn)行繪制
    if (!isProtected) {
      ctx.fillRect(
        nLeft,
        nTop,
        (isProtected ? (isBlkPosCtr ? 1 : 1) : dataScale) * nSize,
        (isProtected ? (isBlkPosCtr ? 1 : 1) : dataScale) * nSize
      );
    }
  }
}

此時已經(jīng)繪制出二維碼的數(shù)據(jù)碼區(qū):

怎么利用小程序的canvas來繪制二維碼

2.5 繪制圖形識別區(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 完畢

這時候,一個樸素的二維碼就繪制成功啦~

以上就是怎么利用小程序的canvas來繪制二維碼,小編相信有部分知識點(diǎn)可能是我們?nèi)粘9ぷ鲿姷交蛴玫降?。希望你能通過這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI