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>
相关推荐
前端 贾公子2 分钟前
ElementUI 中 validateField 对部分表单字段数组进行校验时多次回调问题
前端·javascript·elementui
棒棒的唐2 分钟前
vue2 elementUI 登录页面实现回车提交登录的方法
前端·javascript·elementui
前端小万5 分钟前
一次紧急的现场性能问题排查
前端·性能优化
zhangzuying10266 分钟前
基于Vue3 +ElementuiPlus + Dexie.js自研的浏览器插件新建标签页tab
vue.js·typescript·echarts
lichong95111 分钟前
【混合开发】vue+Android、iPhone、鸿蒙、win、macOS、Linux之video 的各种状态和生命周期调用说明
android·vue.js·macos
excel21 分钟前
为什么相同卷积代码在不同层学到的特征完全不同——基于 tfjs-node 猫图像识别示例的逐层解析
前端
知识分享小能手22 分钟前
React学习教程,从入门到精通,React 使用属性(Props)创建组件语法知识点与案例详解(15)
前端·javascript·vue.js·学习·react.js·前端框架·vue
用户214118326360224 分钟前
dify案例分享-免费玩转即梦 4.0 多图生成!Dify 工作流从搭建到使用全攻略,附案例效果
前端
CodeSheep24 分钟前
稚晖君又开始摇人了,有点猛啊!
前端·后端·程序员
JarvanMo26 分钟前
Flutter Web vs Mobile:主要区别以及如何调整你的UI
前端