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>

五、恭喜恭喜

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

相关推荐
开心工作室_kaic1 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
刚刚好ā1 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
沉默璇年2 小时前
react中useMemo的使用场景
前端·react.js·前端框架
yqcoder2 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
2401_882727572 小时前
BY组态-低代码web可视化组件
前端·后端·物联网·低代码·数学建模·前端框架
SoaringHeart3 小时前
Flutter进阶:基于 MLKit 的 OCR 文字识别
前端·flutter
会发光的猪。3 小时前
css使用弹性盒,让每个子元素平均等分父元素的4/1大小
前端·javascript·vue.js
天下代码客3 小时前
【vue】vue中.sync修饰符如何使用--详细代码对比
前端·javascript·vue.js
猫爪笔记3 小时前
前端:HTML (学习笔记)【1】
前端·笔记·学习·html
前端李易安4 小时前
Webpack 热更新(HMR)详解:原理与实现
前端·webpack·node.js