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

news2024/11/26 16:42:05

一、需求

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

二、参考文章

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

链接:

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

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

三、实现代码

1.qrcode生成二维码

下载依赖

npm i qrcode

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

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:这里只生成了二维码

<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: 

<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在这里用定位定到二维码中间,我将名片也封装了一个组件
    <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>
这里是下载使用的组件
       <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>
<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的形式定位到盒子上,下载后就清晰很多啦

  // background-image: url("../../../../../assets/images/userCard/card.png");
  // background-size: cover;
    <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>

五、恭喜恭喜

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2232006.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【AIGC】深入探索『后退一步』提示技巧:激发ChatGPT的智慧潜力

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;“后退一步”技巧介绍技巧目的 &#x1f4af;“后退一步”原理“后退一步”提示技巧与COT和TOT的对比实验验证 &#x1f4af;如何应用“后退一步”策略强调抽象思考引导提…

Python | Leetcode Python题解之第520题检测大写字母

题目&#xff1a; 题解&#xff1a; class Solution:def detectCapitalUse(self, word: str) -> bool:# 若第 1 个字母为小写&#xff0c;则需额外判断第 2 个字母是否为小写if len(word) > 2 and word[0].islower() and word[1].isupper():return False# 无论第 1 个字…

【python ASR】win11-从0到1使用funasr实现本地离线音频转文本

文章目录 前言一、前提条件安装环境Python 安装安装依赖,使用工业预训练模型最后安装 - torch1. 安装前查看显卡支持的最高CUDA的版本&#xff0c;以便下载torch 对应的版本的安装包。torch 中的CUDA版本要低于显卡最高的CUDA版本。2. 前往网站下载[Pytorch](https://pytorch.o…

Java日志脱敏——基于logback MessageConverter实现

背景简介 日志脱敏 是常见的安全需求&#xff0c;最近公司也需要将这一块内容进行推进。看了一圈网上的案例&#xff0c;很少有既轻量又好用的轮子可以让我直接使用。我一直是反对过度设计的&#xff0c;而同样我认为轮子就应该是可以让人拿去直接用的。所以我准备分享两篇博客…

Java面试经典 150 题.P26. 删除有序数组中的重复项(003)

本题来自&#xff1a;力扣-面试经典 150 题 面试经典 150 题 - 学习计划 - 力扣&#xff08;LeetCode&#xff09;全球极客挚爱的技术成长平台https://leetcode.cn/studyplan/top-interview-150/ 题解&#xff1a; class Solution {public int removeDuplicates(int[] nums) …

Prometheus套装部署到K8S+Dashboard部署详解

1、添加helm源并更新 helm repo add prometheus-community https://prometheus-community.github.io/helm-charts helm repo update2、创建namespace kubectl create namespace monitoring 3、安装Prometheus监控套装 helm install prometheus prometheus-community/prome…

如何选择到印尼的海运代理

如何选择到印尼的海运代理 选择合适的海运代理的重要性 海运代理负责安排货物从发货地到目的地的整个运输过程&#xff0c;包括装运、清关、仓储等服务。一个可靠的海运代理能确保货物安全准时到达&#xff0c;并帮助企业节省时间和成本。 选择海运代理需考虑的主要因素 公司…

python常用的第三方库下载方法

方法一&#xff1a;打开pycharm-打开项目-点击左侧图标查看已下载的第三方库-没有下载搜索后点击install即可直接安装--安装成功后会显示在installed列表 方法二&#xff1a;打开dos窗口输入命令“pip install requests“后按回车键&#xff0c;看到successfully既安装成功&…

FFmpeg 4.3 音视频-多路H265监控录放C++开发八,使用SDLVSQT显示yuv文件 ,使用ffmpeg的AVFrame

一. AVFrame 核心回顾&#xff0c;uint8_t *data[AV_NUM_DATA_POINTERS] 和 int linesize[AV_NUM_DATA_POINTERS] AVFrame 存储的是解码后的数据&#xff0c;&#xff08;包括音频和视频&#xff09;例如&#xff1a;yuv数据&#xff0c;或者pcm数据&#xff0c;参考AVFrame结…

jenkins 构建报错 Cannot run program “sh”

原因 在 windows 操作系统 jenkins 自动化部署的时候, 由于自动化构建的命令是 shell 执行的,而默认windows 从 path 路径拿到的 shell 没有 sh.exe &#xff0c;因此报错。 解决方法 前提是已经安装过 git WINR 输入cmd 打开命令行, 然后输入where git 获取 git 的路径, …

基于Spring Boot的高校物品捐赠管理系统设计与实现,LW+源码+讲解

摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装高校物品捐赠管理系统软件来发挥其高效地信息处理的作用&a…

AndroidStudio通过Bundle进行数据传递

作者&#xff1a;CSDN-PleaSure乐事 欢迎大家阅读我的博客 希望大家喜欢 使用环境&#xff1a;AndroidStudio 目录 1.新建活动 2.修改页面布局 代码&#xff1a; 效果&#xff1a; 3.新建类ResultActivity并继承AppCompatActivity 4.新建布局文件activity_result.xml 代…

测试分层:减少对全链路回归依赖的探索!

引言&#xff1a;测试分层与全链路回归的挑战 在软件开发和测试过程中&#xff0c;全链路回归测试往往是一个复杂且耗费资源的环节&#xff0c;尤其在系统庞大且模块众多的场景下&#xff0c;全链路测试的集成难度显著提高。而“测试分层”作为一种结构化的测试方法&#xff0…

【python】OpenCV—findContours(4.5)

文章目录 1、功能描述2、原理分析3、代码实现4、效果展示5、完整代码6、参考 1、功能描述 输入图片&#xff0c;计算出图片中的目标到相机间的距离 2、原理分析 用最简单的三角形相似性 已知参数&#xff0c;物体的宽度 W W W&#xff0c;物体到相机的距离 D D D&#xff0…

jmeter基础01-3_环境准备-Linux系统安装jdk

Step1. 查看系统类型 打开终端&#xff0c;命令行输入uname -a&#xff0c;显示所有系统信息&#xff0c;包括内核名称、主机名、内核版本等。 如果输出是x86_64&#xff0c;则系统为64位。如果输出是i686 或i386&#xff0c;则系统为32位。 Step2. 官网下载安装包 https://www…

获取JSON对象的时候,值会自动带上双引号

问题&#xff1a;当使用下方代码&#xff0c;获取JsonNode对象的时候&#xff0c;从该对象中通过键获取的值会自动带上双引号。 JsonNode jsonNode new ObjectMapper().readTree("JSON字符串"); 注意&#xff1a;以上方法是获得的JsonNode对象&#xff0c;不是JSO…

大气污染监测系统方案:智慧环保监测的“千里眼“

​ 作为星创易联的一名工程师,我有幸参与了某市环保局的大气污染监测系统项目。该市地处我国中部地区,近年来工业发展迅速,大气污染问题日益突出。为加强环境管理,政府决定构建一套覆盖全市的大气污染在线监测系统,实时掌握各区域的空气质量状况。 我们公司凭借在物联网领域的…

leetcode-88-合并两个有序数组

题解&#xff1a; 解法一&#xff1a;从后向前同时遍历两个数组&#xff0c;因为nums1后面是0&#xff0c;从后遍历节省空间。 1、定义三个指针&#xff0c;分别为&#xff1a;len1m-1指向nums1的最后一个非0数字&#xff1b;len2n-1指向nums2的最后一个数字&#xff1b;len3…

百度文心智能体:巧用汉字笔画生成与汉字搜索插件,打造一个学习汉字的教育类智能体

这篇文章&#xff0c;主要介绍如何巧用汉字笔画生成与汉字搜索插件&#xff0c;打造一个学习汉字的教育类智能体。 目录 一、教育类智能体 1.1、智能体演示 1.2、智能体插件 1.3、智能体prompt &#xff08;1&#xff09;角色和目标 &#xff08;2&#xff09;思考路径 …

MySQL rand()函数、rand(n)、生成不重复随机数

文章目录 一、rand()与rand(n)二、rand()使用示例2.1、rand()与order by/group by使用随机排序分组2.2、round()与rand()的组合使用2.3、rand与ceiling的组合使用2.4、rand与floor组合使用2.5、rand与md5组合使用 三、总结3.1、rand()与rand(n)的区别 有时候我们想要生成一个唯…