首頁  >  文章  >  微信小程式  >  如何利用小程式的canvas來繪製二維碼?

如何利用小程式的canvas來繪製二維碼?

青灯夜游
青灯夜游轉載
2022-01-06 10:11:056011瀏覽

微信小程式如何產生二維碼?以下這篇文章跟大家介紹一下利用小程式的canvas能力繪製二維碼的方法,希望對大家有幫助!

如何利用小程式的canvas來繪製二維碼?

在微信小程式的業務中會有一些需要展示二維碼的場景。靜態二維碼可以直接存放在本地,使用圖片方式展示,但不適合根據使用者相關資訊產生動態的二維碼。本文將介紹下利用小程式的canvas能力繪製二維碼。

1 方法一:透過wx-qr直接產生

1.1 DEMO

# #微信開發者工具開啟檢視

#

1.2 安裝

# 通过 npm 安装
npm i wx-qr -S

# 通过 yarn 安装
yarn add wx-qr

#1.3 使用元件

##首先在你所開發的小程式根目錄 

app.json 或需要使用該元件的 xxx.json 中引用元件

(注意:請勿將元件命名為 

wx-xxx 開頭,可能會導致微信小程式解析tag 失敗)

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

之後就可以在

wxml 中直接使用元件

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

當然,還可以支援很多種配置,詳見

github 或 碼雲文件。

2. 方式二:基於QRCode.js結合canvas繪製

#2.0 二維碼的組成部分

如何利用小程式的canvas來繪製二維碼?

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

  • Timing Patterns也是用來定位的。原因是二維碼有40種尺寸,尺寸過大了後需要有根標準線,不然掃描的時候可能會掃歪了。

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

功能性資料
  • Format Information 存在於所有的尺寸中,用來存放一些格式化資料的。

  • Version Information 在 >= Version 7以上,需要預留兩塊3 x 6的區域存放一些版本資訊。

資料碼和糾錯碼
    除了上述的那些地方,剩下的地方存放 Data Code 資料碼 和 Error Correction Code 糾錯碼。

2.1 引入二維碼資料產生庫

#複製

qrcode.js至你的小程式相應目錄。

2.2 小程式中建立canvas標籤,並為canvas設定長寬

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

2.3取得canvas實例及上下文

const query = this.createSelectorQuery();
let dpr = wx.getSystemInfoSync().pixelRatio;
query.select(&#39;#qr&#39;).fields({ node: true, size: true, id: true })
  .exec((res) => {
    let { node: canvas, height, width } = res[0];
    let ctx = canvas.getContext(&#39;2d&#39;);
    canvas.width = width * dpr
    canvas.height = height * dpr
    ctx.scale(dpr, dpr);
  })

2.4 定義一些變數及繪製二維碼的資料碼區##其中

QRCodeModel

是從qrCode.js匯入的

// 二维码的颜色
const colorDark = &#39;#000&#39;;
// 获取二维码的大小,因css设置的为750rpx,将其转为px
const rawViewportSize = getPxFromRpx(750);
// 二维码容错率{ L: 1, M: 0, Q: 3, H: 2 }
const correctLevel = 0;
// 创建二维码实例对象,并添加数据进行生成
const qrCode = new QRCodeModel(-1, correctLevel);
qrCode.addData(url);
qrCode.make();

// 每个方向的二维码数量
const nCount = qrCode.moduleCount;
// 计算每个二维码方块的大小
const nSize = getRoundNum(rawViewportSize / nCount, 3)
// 每块二维码点的大小比例
const dataScale = 1;
// 计算出dataScale不为1时,每个点的偏移值
const dataXyOffset = (1 - dataScale) * 0.5;
// 循环行列绘制数据码区
for (let row = 0; row < nCount; row++) {
  for (let col = 0; col < nCount; col++) {
    // row 和 col 处的模块是否是黑色区
    const bIsDark = qrCode.isDark(row, col);
    // 是否是二维码的图案定位标识区 Position Detection Pattern(如本模块,是三个顶点位置处的大方块)
    const isBlkPosCtr = (col < 8 && (row < 8 || row >= nCount - 8)) || (col >= nCount - 8 && row < 8);
    // 是否是Timing Patterns,也是用于协助定位扫描的
    const isTiming = (row == 6 && col >= 8 && col <= nCount - 8) || (col == 6 && row >= 8 && row <= nCount - 8);
    // 如果是这些区域 则不进行绘制
    let isProtected = isBlkPosCtr || isTiming;
    // 计算每个点的绘制位置(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)";
    // 如果不是标识区,则进行绘制
    if (!isProtected) {
      ctx.fillRect(
        nLeft,
        nTop,
        (isProtected ? (isBlkPosCtr ? 1 : 1) : dataScale) * nSize,
        (isProtected ? (isBlkPosCtr ? 1 : 1) : dataScale) * nSize
      );
    }
  }
}
此時已經繪製出二維碼的資料碼區:

如何利用小程式的canvas來繪製二維碼?

##2.5 繪製圖形辨識區

// 绘制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來繪製二維碼?具體程式碼詳見微信小程式碼片段

https://developers.weixin.qq.com/s/WHJj73mX7bwv

此程式碼只是提供了一個簡單二維碼的生成邏輯。若需要更複雜的二維碼展示功能,還是建議使用

wx-qr
或參考裡面的具體程式碼。歡迎各位提Issue與Star~~

【相關學習推薦:小程式開發教學

如何利用小程式的canvas來繪製二維碼?#含背景圖
如何利用小程式的canvas來繪製二維碼?#含logo
如何利用小程式的canvas來繪製二維碼?含logo 背景圖

以上是如何利用小程式的canvas來繪製二維碼?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除