Bootstrap

vue 项目 QrcodeVue 生成二维码之后使用原生JS代码实现下载保存为图片

前言

  其实吧,QrcodeVue  配合html2canvas 可以完美实现上述功能,只是考虑到我们只是把QrcodeVue生成的svg 转化为图片并下载不用去引入三方库实现,而是只用几十行代码就能搞定,节省2M的html2canvas打包空间。

废话不多说,直接上代码。代码中调用的方法newDownLoad() 内容即为实现 将svg 转化为 canvas 然后下载为图片

代码

<template>
  <div v-if="visible" class="qr-code-component sys-flex-column sys-flex-center">
    <div class="qr-code-container sys-flex-column">
      <div class="close-icon-container sys-flex-row sys-flex-center" @click="close">
        <i class="iconfont icon-guanbi1"></i>
      </div>
      <!--<div class="qr-code-header">-->
      <!--<h3>题目二维码</h3>-->
      <!--</div>-->
      <div class="qr-code-body sys-flex-column sys-flex-center flex1">
        <div style="border: 1px solid #eeeeee;">
          <div :id="shotDomId" class="screen-shot sys-flex-column sys-flex-center">
            <qrcode-vue id="my-practise-qrcode" :value="qrcodeUrl" :size="200" renderAs="svg" background="#fff" :foreground="color" level="M">
            </qrcode-vue>

            <div :style="{color: color}" v-if="qrcodeTitle" class="practise-id">{{qrcodeTitle}}</div>
          </div>
        </div>
      </div>
      <div class="qr-code-footer sys-flex-row sys-flex-center">
        <el-button type="primary" class="btn" @click="newDownLoad(qrcodeTitle)">下载图片</el-button>
      </div>
    </div>
  </div>
</template>

<script>
import QrcodeVue from 'qrcode.vue'
import logo from './logo'
export default {
  name: 'index',
  components: { QrcodeVue, logo },
  props: {
    qrcodeVal: {
      type: [String, Number],
      required: true
    },
    qrcodeTitle: {
      type: [String, Number],
      required: false
    },
    visible: {
      type: Boolean,
      required: true
    },
    color: {
      type: String,
      required: false,
      default: '#000000'
    }
  },
  data() {
    return {
      shotDomId: ''
    }
  },
  methods: {
    close() {
      this.$emit('close', false)
    },
    newDownLoad(name) {
      const qrcodeElement = document.getElementById('my-practise-qrcode'); 
      // 获取 SVG 子元素
      const svg = qrcodeElement.querySelector('svg')
      const serializer = new XMLSerializer();
      const svgData = serializer.serializeToString(svg); // 将SVG数据转换为Data URL
      const svgBlob = new Blob([svgData], { type: 'image/svg+xml;charset=utf-8' });
      const url = URL.createObjectURL(svgBlob); // 创建一个Image对象 
      const img = new Image();

      img.onload = () => { // 获取Canvas元素

        const wid = svg.width.baseVal.value
        const hei = svg.height.baseVal.value

        const canvas = document.createElement('canvas')
        const ctx = canvas.getContext('2d');
        const padding = 10; // 增加的白色间隙
        canvas.width = wid + 2 * padding;
        canvas.height = hei + 2 * padding + 20; // 增加底部文字的高度


        // 绘制白色背景
        ctx.fillStyle = 'white';
        ctx.fillRect(0, 0, canvas.width, canvas.height);

         // 绘制二维码图片
        ctx.drawImage(img, padding, padding, wid, hei);

        // 绘制文本
        const text = name;
        const fontSize = 16;
        const fontWeight = 'bold';
        ctx.font = `${fontWeight} ${fontSize}px Arial`;
        ctx.textAlign = 'center';
        ctx.textBaseline = 'top';
        ctx.fillStyle = 'black'; // 文本颜色
        const textX = canvas.width / 2;
        const textY = canvas.height - 25; // 文本位置在底部中央
        ctx.fillText(text, textX, textY);

        // 将 canvas 转换为 Data URL
        const dataURL = canvas.toDataURL('image/png');
        const a = document.createElement('a');
        a.href = dataURL;
        a.download = `${name}.png`;
        a.target = '_blank';
        a.click();

        URL.revokeObjectURL(url);
      }
      img.src = url;
    }
  },
  beforeDestroy() {
    let html = document.getElementsByTagName('html')[0]
    html.style.overflow = ''
  },
  watch: {
    visible: {
      handler(N, O) {
        let html = document.getElementsByTagName('html')[0]
        html.style.overflow = N ? 'hidden' : ''
        this.shotDomId = 'screen-shot-dom-' + new Date().getTime()
      },
      immediate: true
    }
  },
  computed: {
    qrcodeUrl() {
   	  const QRurl = 'https://xxx.xxxx.com' 
      return QRurl
    }
  }
}
</script>

<style lang="scss">
.qr-code-component {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: rgba(0, 0, 0, 0.5);
  z-index: 9999;
  .qr-code-container {
    background: #ffffff;
    width: 332px;
    height: 424px;
    border-radius: 20px;
    position: relative;
    .close-icon-container {
      width: 26px;
      height: 26px;
      overflow: hidden;
      border: 2px solid #ffffff;
      border-radius: 50%;
      background: #c8c9ca;
      color: #ffffff;
      position: absolute;
      top: -30px;
      right: -30px;
      cursor: pointer;
      i {
        margin: 0 !important;
        font-size: 18px;
      }
    }
    .qr-code-header {
      height: 40px;
      background: #efefef;
      line-height: 40px;
      padding: 0 20px;
      border-bottom: 1px solid #cccccc;
    }
    .qr-code-body {
      /*background: red;*/
      padding-top: 40px;
      .screen-shot {
        padding: 20px 20px 10px 20px;
        .practise-id {
          font-size: 16px;
          font-weight: bolder;
          margin-top: 10px;
        }
      }
    }
    .qr-code-footer {
      height: 120px;
      .btn {
        height: 41px;
        width: 120px;
      }
    }
  }
  .qrcode-icon {
    position: absolute;
    width: 45px;
    height: 60px;
    background: #f7f7f7;
    left: 143px;
    top: 131px;
  }
}
</style>

;