0 the introduction

There will be some scenes that need to show two-dimensional code in the business of wechat mini program. Static TWO-DIMENSIONAL code can be stored locally and displayed by pictures, but it is not suitable to generate dynamic two-dimensional code according to user information. This article will introduce the use of small program canvas ability to draw two-dimensional code.

1 Method 1: Passwx-qrDirectly generated

1.1 the DEMO

Open wechat developer tool to view

Including background

Contain logo

Contains logo and background image

1.2 installation

Install via NPM
npm i wx-qr -S

# Install using YARN
yarn add wx-qr
Copy the code

1.3 Using Components

Start by referencing the component in the app.json root of the applet you are developing, or in xxx.json where you need to use the component

(Note: Please do not name the component starting with WX-XXX, which may cause wechat applets to fail to resolve the tag.)

{
  "usingComponents": {
    "qr-container": "wx-qr"}}Copy the code

You can then use components directly in WXML

<qr-container text="{{qrTxt}}" size="750"></qr-container>
Copy the code

Page({
    data: {
        qrTxt: 'https://github.com/liuxdi/wx-qr',}});Copy the code

Of course, you can also support a variety of configurations, see github or code cloud documentation.

2. Method 2: Draw with Canvas based on Qrcode. js

Component of 2.0 QR code

Positioning design
  • Position Detection Pattern is a positioning Pattern used to mark the rectangular size of the TWO-DIMENSIONAL code. Separators for Postion Detection Patterns. The reason that three instead of four means that three can identify a rectangle.

  • Timing Patterns are also used for positioning. The reason is that the TWO-DIMENSIONAL code has 40 sizes, the size is too large after the need to have a standard line, otherwise when scanning may sweep crooked.

  • Only qr codes above Version2 (including Version2) require this Alignment pattern, which is also used for positioning.

Functional data
  • Format Information exists at all sizes and is used to store some formatted data.

  • If Version Information is greater than or equal to Version 7, two 3 x 6 areas must be reserved for storing Version Information.

Data code and error correction code
  • In addition to the above places, the remaining places store the Data Code and Error Correction Code.

2.1 Introduction of two-dimensional code data generation library

Copy qrcode.js to the appropriate directory for your applet.

2.2 Create canvas tag in the mini-program and set the length and width of canvas

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

2.3 Obtaining canvas instance and context

const query = this.createSelectorQuery();
let dpr = wx.getSystemInfoSync().pixelRatio;
query.select('#qr').fields({ nodetrue.sizetrue.idtrue })
  .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);
  })
Copy the code

2.4 Define some variables and draw the data code area of two-dimensional code

QRCodeModel is imported from qrcode.js

// Color of the qr code
const colorDark = '# 000';
// Get the size of the qr code. Since CSS is set to 750rpx, convert it to PX
const rawViewportSize = getPxFromRpx(750);
// Error tolerance of two-dimensional code {L: 1, M: 0, Q: 3, H: 2}
const correctLevel = 0;
// Create a qr code instance object and add data to generate it
const qrCode = new QRCodeModel(-1, correctLevel);
qrCode.addData(url);
qrCode.make();

// The number of qr codes in each direction
const nCount = qrCode.moduleCount;
// Calculate the size of each qr code square
const nSize = getRoundNum(rawViewportSize / nCount, 3)
// The size ratio of each QR code dot
const dataScale = 1;
// Calculate the offset of each point if dataScale is not 1
const dataXyOffset = (1 - dataScale) * 0.5;
// Loop row to draw the data code area
for (let row = 0; row < nCount; row++) {
  for (let col = 0; col < nCount; col++) {
    // Whether the modules at row and col are black
    const bIsDark = qrCode.isDark(row, col);
    Position Detection Pattern (for example, in this module, it is a big square at three vertices)
    const isBlkPosCtr = (col < 8 && (row < 8 || row >= nCount - 8)) || (col >= nCount - 8 && row < 8);
    // Whether Timing Patterns are used to help locate scans
    const isTiming = (row == 6 && col >= 8 && col <= nCount - 8) || (col == 6 && row >= 8 && row <= nCount - 8);
    // If it is these regions, it will not be drawn
    let isProtected = isBlkPosCtr || isTiming;
    // Calculate the drawing position of each point (left, top)
    const nLeft = col * nSize + (isProtected ? 0 : dataXyOffset * nSize);
    const nTop = row * nSize + (isProtected ? 0 : dataXyOffset * nSize);
    // Stroke color, line width, fill color configuration
    ctx.strokeStyle = colorDark;
    ctx.lineWidth = 0.5;
    ctx.fillStyle = bIsDark ? colorDark : "Rgba (255, 255, 255, 0.6)";
    // If not, draw
    if(! isProtected) { ctx.fillRect( nLeft, nTop, (isProtected ? (isBlkPosCtr ?1 : 1) : dataScale) * nSize,
        (isProtected ? (isBlkPosCtr ? 1 : 1) : dataScale) * nSize ); }}}Copy the code

At this point, the data code area of the TWO-DIMENSIONAL code has been drawn:

2.5 Draw a graphic identification area

// Draw 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 is drawn

// Draw 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);
}
// Finish drawing Timing Patterns
Copy the code

At this time, a simple TWO-DIMENSIONAL code is drawn successfully ~

See the code snippet for details

The code just provides a simple QR code generation logic. If more complex TWO-DIMENSIONAL code display function is required, it is recommended to use WX-QR or refer to the specific code inside. Welcome to Issue and Star

reference

Two-dimensional code generation details and principles

qrcode-generator