Skip to content

二维码解决方案

二维码由服务端生成,前端无需考虑。

vue-qrcode

todo

qrcode

国外开源,使用率较高,稳定,跨平台

但是原生不支持中间logo,需要自己实现

https://www.npmjs.com/package/qrcode

html 使用需要使用 canvas

html
<canvas v-if="props.qr" class="qr-code" ref="model-qr-code"></canvas>
ts
import { throttle } from '@/util'
import qrcode, { type QRCodeRenderersOptions } from 'qrcode'
import { useTemplateRef, nextTick } from 'vue'

import logo from '@/assets/logo.ico'

export const useQRCode = (refName: string, conf: QRCodeRenderersOptions = {}) => {
  const qrdom = useTemplateRef(refName)

  const addLogo = (canvas?: HTMLCanvasElement) => {
    if (!canvas || !canvas.getContext) return

    const ctx = canvas.getContext('2d')
    if (!ctx) return

    const img = new Image()
    img.crossOrigin = 'Anonymous' //解决Canvas.toDataURL 图片跨域问题
    img.src = logo
    img.onload = () => {
      const codeWidth = (canvas.clientWidth * 0.75) / 2
      const codeHeight = (canvas.clientHeight * 0.75) / 2
      ctx.drawImage(
        img,
        codeWidth,
        codeHeight,
        canvas.clientWidth * 0.25,
        canvas.clientHeight * 0.25
      )
    }
  }

  const setQRCode = (url: string) => {
    if (!qrdom || !qrdom.value) {
      return nextTick(() => {
        setQRCode(url)
      })
    }

    qrcode.toCanvas(
      qrdom.value,
      url,
      {
        errorCorrectionLevel: 'H',
        margin: 0,
        ...conf
      },
      (error: any) => {
        if (error) {
          console.error(error)
        } else {
          addLogo(qrdom.value as HTMLCanvasElement)
        }
      }
    )
  }

  return { setQRCode: throttle(setQRCode, 100) }
}

参考:https://www.guijiaow.com/2024/08/8816.html

qrcodejs2

vue3中有bug,使用qrcodejs2-fix

html 使用需要使用 div

ts
// qrcodejs2 无法使用会出现  Cannot read properties of undefined (reading '_android')
// 先使用 qrcodejs2-fix 处理
// @ts-ignore
import { throttle } from '@/util'
// @ts-ignore
import QRCode from 'qrcodejs2-fix'
import { useTemplateRef, nextTick } from 'vue'

export const useQRCode = (refName: string, conf: QRCodeRenderersOptions = {}) => {
  let lastQRCode: any
  const qrdom = useTemplateRef(refName)

  const setQRCode = (url: string) => {
    // console.log('qr div is', qrdiv.value)
    if (!qrdom || !qrdom.value) {
      return nextTick(() => {
        setQRCode(url)
      })
    }

    if (lastQRCode) {
      lastQRCode.clear()
    }

    lastQRCode = new QRCode(qrdiv.value, {
      text: url,
      width: 200,
      height: 200
    })


  return { setQRCode: throttle(setQRCode, 100) }
}