Vue生成名片二维码带logo并支持下载

一、需求

生成一张名片,名片上有用户信息以及二维码,名片支持下载功能(背景样式可更换,忽略本文章样图样式)。

二、参考文章

这不是我自己找官网自己摸索出来的,是借鉴各位前辈的,学以致用,自己运用到项目中实现需求,做个记录,以便将来需要,方便查看

链接:

Vue中两种生成二维码(带logo)并下载方式_vue qrcode logo图标-CSDN博客

vue中html2canvas的使用_vue html2canvas-CSDN博客

三、实现代码

1.qrcode生成二维码

下载依赖

npm i qrcode

注:这里我将生成二维码的实现封装成一个组件,以便复用

HTML:

html 复制代码
<template>
  <div class="qrcode-box">
     <!-- 二维码主要部分 -->
    <canvas id="canvas" ref="qrCanvas" title="扫描二维码"></canvas>
     <!-- logo 用定位定到二维码中间的 -->
    <div class="card-logo">
      <img
        src="../../assets/images/userCard/card_logo.png"
        class="card-img"
        alt="名片"
      />
    </div>
  </div>
</template>

JS:这里只生成了二维码

javascript 复制代码
<script>
import QRCode from "qrcode"; //引入生成二维码插件
export default {
  name: "qrcode",
  props: {
    canvasWidth: {//画布的宽度
      default: 87,
      type: Number,
    },
    canvasHeight: {//画布的高度
      default: 87,
      type: Number,
    },
    url: {//生成二维码的地址
      default: "",
      // type: String,
      required: true,
    },
    logoUrl: {//二维码的logo
      default: require("@/assets/images/userCard/card_logo.png"),
      type: String,
      // required:true
    },
  },
  mounted() {
    //生成二维码
    this.generateQRCode();
    //设置logo图标,这里是可以生成logo的,但是设计稿的二维码宽高小于100,导致生成的二维码模糊,所以我用定位的方式将logo定位到二维码中间
    // if (this.logoUrl != "") {
    //   let myCanvas = this.$refs.qrCanvas;
    //   let ctx = myCanvas.getContext("2d");
    //   // 在Canvas画布 添加图片
    //   let img = new Image();
    //   // img.setAttribute("crossOrigin", "Anonymous");
    //   img.crossOrigin = "Anonymous"; //解决Canvas.toDataURL 图片跨域问题
    //   img.src = this.logoUrl;
    //   img.onload = () => {
    //     //第一个设置的元素,第二三是位置,后面两个是宽和高
    //     //居中的位置计算为 (二维码宽度-img宽度)/2
    //     let codeWidth = (this.canvasWidth * 0.75) / 2;
    //     let codeHeight = (this.canvasHeight * 0.75) / 2;
    //     ctx.drawImage(
    //       img,
    //       codeWidth,
    //       codeHeight,
    //       this.canvasWidth * 0.25,
    //       this.canvasHeight * 0.25
    //     );
    //   };
    // }
  },
  data() {
    return {};
  },
  methods: {
    // 生成的二维码宽高小于100的时候会读取不到信息,生成的二维码信息不够齐全,模糊
    generateQRCode() {
      let opts = {
        errorCorrectionLevel: "M", //4个容错级别(L:7%, M: 15%, Q: 25%, H: 30%),指二维码被遮挡可以扫出结果的区域比例
        type: "image/png", //生成的二维码类型
        quality: 0.3, //二维码质量
        margin: 1, //二维码留白边距
        width: this.canvasWidth, //宽
        height: this.canvasHeight, //高
        text: "1111", //二维码内容
        color: {
          light: "#ffffff", //背景色
        },
      };
      // 将获取到的数据(val)画到msg(canvas)上,加上时间戳动态生成二维码
      const canvas = this.$refs.qrCanvas;
      QRCode.toCanvas(canvas, this.url, opts, (error) => {
        if (error) console.error(error);
      });
    },
  },
};
</script>

CSS:

css 复制代码
<style lang="scss" scoped>
.qrcode-box {
  position: relative;
  .card-logo {
    width: 20px;
    height: 20px;
    position: absolute;
    top: 34px;
    left: 34px;
    img {
      width: 100%;
      height: 100%;
    }
  }
}
</style>

2.html2canvas 生成图片(这里只展示部分代码)

二维码logo在这里用定位定到二维码中间,我将名片也封装了一个组件
html 复制代码
    <div class="qrcode_pic" v-if="cardInfo.qrCodeUrl">
      <QRcodeComponent :url="cardInfo.qrCodeUrl" />
      <div class="qrcode_text">
        <img
          src="../../../../../assets/images/userCard/qrcode_text.png"
          class="code-img"
          alt="二维码"
        />
      </div>
    </div>
这里是下载使用的组件
html 复制代码
       <div class="card-box">
            <div class="down_btn">
              <el-button type="text" @click="download">
                <i class="el-icon-download"></i>
                下载</el-button
              >
            </div>
            <div ref="content" class="down-content">
              <UserCard />
            </div>
          </div>
javascript 复制代码
<script>
import html2canvas from "html2canvas";

data(){
   download() {
      const ref = this.$refs.content; // 截图区域
      html2canvas(ref, {
        // 以下字段可选
        width: 560, // canvas宽度
        height: 355, // canvas高度
        x: 0, // x坐标
        y: 0, // y坐标
        scrollY: 0,
        scrollX: 0,
        backgroundColor: null,
        // backgroundColor: "#e8f4ff",
        padding:0,
        borderRadius: 5,
        scale: 2, // 处理模糊问题:按照比例增加分辨率,默认值1,
        dpi: 300, // 处理模糊问题:每英寸的像素,也就是扫描精度,dpi越低,扫描清晰度越低,默认值96,建议修改为300
        useCORS: true, // 如果截图的内容里有图片,可能会有跨域的情况,加上这个参数,解决文件跨域问题
      }).then((canvas) => {
        const dataURL = canvas.toDataURL("image/png");
        const creatDom = document.createElement("a");
        document.body.appendChild(creatDom);
        creatDom.href = dataURL;
        creatDom.download = "我的名片";
        creatDom.click();
      });
    },
}
</script>

四、遇到的问题及解决方案

1.二维码logo模糊

刚开始我是在mounted里直接用画布生成,但是很模糊,经过查找发现可以用定位将logo定到二维码中间,可以实现效果,在上面代码上有注释标明。

2.名片下载模糊

之前我是将图片以背景图片的形式放到盒子里,这样我用html2canvas 生成图片下载下来后很模糊,我就用img的形式定位到盒子上,下载后就清晰很多啦

css 复制代码
  // background-image: url("../../../../../assets/images/userCard/card.png");
  // background-size: cover;
html 复制代码
    <div class="qrcode_pic" v-if="cardInfo.qrCodeUrl">
      <QRcodeComponent :url="cardInfo.qrCodeUrl" />
      <div class="qrcode_text">
        <img
          src="../../../../../assets/images/userCard/qrcode_text.png"
          class="code-img"
          alt="二维码"
        />
      </div>
    </div>

五、恭喜恭喜

恭喜你我又学会了新的东西,真棒呀真棒呀,祝你我今天开心呐,有问题请留言,看见就会回的,不过不一定会。

相关推荐
卸任6 小时前
Vibe coding工具使用心得
前端·ai编程
brien97 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance7 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M7 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写7 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李7 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易8 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
清晨Coding8 小时前
删了 Cookie 还能自动登录?Google系网站登录态自动恢复的原理分析
javascript
风骏时光牛马8 小时前
前沿视界
前端
kyriewen8 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员