vue生成二维码图片+文字说明

发布于:2025-06-11 ⋅ 阅读:(19) ⋅ 点赞:(0)

需求:点击下载图片,上方是二维码,下方显示该二维码的相关内容,并且居中显示,支持换行

解决方案步骤:

1. 使用qrcode生成二维码的DataURL。

2. 创建canvas,将二维码图片绘制到canvas的上半部分。

3. 在canvas的下半部分绘制文字,处理换行和样式。

4. 将canvas转换为图片,触发下载。

具体实现步骤:

1、安装依赖

npm install qrcode --save

2、组件实现

<template>
  <div>
    <button @click="generateAndDownload">下载图片</button>
    <canvas ref="canvas" style="display: none;"></canvas>
  </div>
</template>

<script>
import QRCode from 'qrcode'

export default {
  data() {
    return {
      canvasWidth: 400,    // 画布宽度
      canvasHeight: 400,   // 画布高度
      qrSize: 300,        // 二维码尺寸
      textConfig: {        // 文字配置
        content: '这是图片的文字说明部分,支持自动换行功能,当文字超过宽度限制时会自动换行显示。',
        x: 40,
        y: 320,
        lineHeight: 24,
        maxWidth: 320,     // canvasWidth - 80
        fontSize: '16px Arial',
        color: 'black'
      }
    }
  },
  methods: {
    // 文字换行处理
    wrapText(ctx, text, x, y, maxWidth, lineHeight) {
      const chars = text.split('')
      let line = ''
      let testLine = ''

      // 设置精确文本测量基线
      ctx.textBaseline = 'top'
      let xCoord = x
      for (let i = 0; i < chars.length; i++) {
        testLine = line + chars[i]
        const metrics = ctx.measureText(testLine)

        if (metrics.width > maxWidth && i > 0) {
          ctx.fillText(line, x, y)
          line = chars[i]
          y += lineHeight
        } else {
          line = testLine
          // 居中显示文字
          xCoord = (maxWidth - metrics.width) / 2 + 40
        }
      }
      ctx.fillText(line, xCoord, y)
    },

    // 生成并下载图片
    async generateAndDownload() {
      const canvas = this.$refs.canvas
      if (!canvas) return
      
      // 初始化画布
      canvas.width = this.canvasWidth
      canvas.height = this.canvasHeight
      const ctx = canvas.getContext('2d')
      if (!ctx) return

      try {
        // 绘制背景
        ctx.fillStyle = 'white'
        ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight)

        // 生成二维码
        const qrDataURL = await QRCode.toDataURL('https://example.com', { width: this.qrSize })
        await new Promise(resolve => {
          const img = new Image()
          img.onload = () => {
            // 居中绘制二维码
            const margin = (this.canvasWidth - this.qrSize) / 2
            ctx.drawImage(img, margin, 20, this.qrSize, this.qrSize)
            resolve()
          }
          img.src = qrDataURL
        })

        // 绘制文字
        ctx.fillStyle = this.textConfig.color
        ctx.font = this.textConfig.fontSize
        this.wrapText(
          ctx,
          this.textConfig.content,
          this.textConfig.x,
          this.textConfig.y,
          this.textConfig.maxWidth,
          this.textConfig.lineHeight
        )

        // 触发下载
        const link = document.createElement('a')
        link.download = 'qr-with-text.png'
        link.href = canvas.toDataURL('image/png')
        link.click()
      } catch (error) {
        console.error('生成失败:', error)
      }
    }
  }
}
</script>