微信小程序生成二维码框架

(1) createQrCode.ts:

/**
create-qrcode.js
================
基于 qr.js 进行包装, 适用于小程序的通用化的 QRCode JS 生成器
qr.js 是已经比较成熟的二维码生成相关的 JS 移植,然而其内部的渲染机制需要浏览器相关特性的支持,使得在小程序端无法直接使用。
小程序中也无法使用 SVG 直接渲染,而如果使用 DOM 结构渲染或者 Canvas 渲染的话,需要的开发和接入成本也会上升。
因此这里使用的方案是: SVG 字符串生成后,转化为 dataURL 字符串,可以直接作为小程序中的 image 标签的 src 属性直接使用。
因为是 SVG 矢量图, 因此可以渲染为任意尺寸。
### INSTALLATION 安装:
在项目中通过 npm 等包管理器安装 qr.js 即可
```bash
npm i qr.js -S
```
### USAGE 调用方法:
```jsx
import createQRCode from './create-qrcode';
<image src={createQRCode({ value: '二维码内容', fgColor: 'black' })} />
```
参数:
 * @param {obj} options
 * @param {string} options.level - 容错级别 L|M|Q|H, 默认为 L
 * @param {string} options.bgColor - 背景色, 默认为 null, 即不使用背景色
 * @param {string} options.fgColor - 前景色, 即二维码的颜色, 默认为黑色
 * @param {boolean} opitons.dataURL - 是否使用 dataURL 生成, 默认为 true, 否则会返回原始 SVG 字符串
 * @returns
 * */

import QRCodeImpl from 'qr.js/lib/QRCode';
import ErrorCorrectLevel from 'qr.js/lib/ErrorCorrectLevel';

function convertStr(str) {
  let out = '';
  for (let i = 0; i < str.length; i++) {
    let charcode = str.charCodeAt(i);
    if (charcode < 0x0080) {
      out += String.fromCharCode(charcode);
    } else if (charcode < 0x0800) {
      out += String.fromCharCode(0xc0 | (charcode >> 6));
      out += String.fromCharCode(0x80 | (charcode & 0x3f));
    } else if (charcode < 0xd800 || charcode >= 0xe000) {
      out += String.fromCharCode(0xe0 | (charcode >> 12));
      out += String.fromCharCode(0x80 | ((charcode >> 6) & 0x3f));
      out += String.fromCharCode(0x80 | (charcode & 0x3f));
    } else {
      // This is a surrogate pair, so we'll reconsitute the pieces and work
      // from that
      i += 1;
      charcode = 0x10000 + (((charcode & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff));
      out += String.fromCharCode(0xf0 | (charcode >> 18));
      out += String.fromCharCode(0x80 | ((charcode >> 12) & 0x3f));
      out += String.fromCharCode(0x80 | ((charcode >> 6) & 0x3f));
      out += String.fromCharCode(0x80 | (charcode & 0x3f));
    }
  }
  return out;
}

function generatePath(modules, margin) {
  const ops: any[] = [];
  modules.forEach((row, y) => {
    let start = null;
    row.forEach((cell, x) => {
      if (!cell && start !== null) {
        // M0 0h7v1H0z injects the space with the move and drops the comma,
        // saving a char per operation
        ops.push(`M${start + margin} ${y + margin}h${x - start}v1H${start + margin}z`);
        start = null;
        return;
      }

      // end of row, clean up or skip
      if (x === row.length - 1) {
        if (!cell) {
          // We would have closed the op above already so this can only mean
          // 2+ light modules in a row.
          return;
        }
        if (start === null) {
          // Just a single dark module.
          ops.push(`M${x + margin},${y + margin} h1v1H${x + margin}z`);
        } else {
          // Otherwise finish the current line.
          ops.push(`M${start + margin},${y + margin} h${x + 1 - start}v1H${start + margin}z`);
        }
        return;
      }

      if (cell && start === null) {
        start = x;
      }
    });
  });
  return ops.join('');
}

/**
 *
 * @param {obj} options
 * @param {string} options.level - 容错级别 L|M|Q|H, 默认为 L
 * @param {string} options.bgColor - 背景色, 默认为 null, 即不使用背景色
 * @param {string} options.fgColor - 前景色, 即二维码的颜色, 默认为黑色
 * @param {boolean} opitons.dataURL - 是否使用 dataURL 生成, 默认为 true, 否则会返回原始 SVG 字符串
 * @returns
 */
export default function createSvg(options) {
  if (typeof options === 'string') options = { value: options };
  options = {
    level: 'M', // L | M | Q | H
    bgColor: null,
    fgColor: '#000000',
    includeMargin: false,
    margin: 0,
    dataURL: true,
    ...options
  };
  const { bgColor, fgColor, value, level, dataURL, margin } = options;
  const qrcode = new QRCodeImpl(-1, ErrorCorrectLevel[level]);
  qrcode.addData(convertStr(value));
  qrcode.make();
  const cells = qrcode.modules;
  const numCells = cells.length + margin * 2;
  const path = generatePath(cells, margin);
  const viewBox = `0 0 ${numCells} ${numCells}`;
  const bgPath = bgColor ? `<path fill="${bgColor}" d="M0,0 h${numCells} v${numCells} H0z" />` : '';
  const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${viewBox}"
    preserveAspectRatio="xMidYMid meet" style="vertical-align: middle;"
  >
    <g>
      ${bgPath}
      <path fill="${fgColor}" d="${path}"></path>
    </g>
  </svg>`;
  if (dataURL) return `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`;
  return svg;
}

(2)引入createQrCode

import createQrCode from "@/utils/createQrCode.ts"

 (3)使用

<image :src="createQRCode(code)" />

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值