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

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

解决方案步骤:

  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>
相关推荐
小约翰仓鼠32 分钟前
vue3子组件获取并修改父组件的值
前端·javascript·vue.js
Lin Hsüeh-ch'in34 分钟前
Vue 学习路线图(从零到实战)
前端·vue.js·学习
烛阴1 小时前
bignumber.js深度解析:驾驭任意精度计算的终极武器
前端·javascript·后端
计蒙不吃鱼1 小时前
一篇文章实现Android图片拼接并保存至相册
android·java·前端
全职计算机毕业设计1 小时前
基于Java Web的校园失物招领平台设计与实现
java·开发语言·前端
啊~哈2 小时前
vue3+elementplus表格表头加图标及文字提示
前端·javascript·vue.js
xiaogg36782 小时前
vue+elementui 网站首页顶部菜单上下布局
javascript·vue.js·elementui
小小小小宇2 小时前
前端小tips
前端
HelloWord~2 小时前
SpringSecurity+vue通用权限系统
vue.js·spring boot
小小小小宇2 小时前
二维数组按顺时针螺旋顺序
前端