一、需求
生成一张名片,名片上有用户信息以及二维码,名片支持下载功能(背景样式可更换,忽略本文章样图样式)。
二、参考文章
这不是我自己找官网自己摸索出来的,是借鉴各位前辈的,学以致用,自己运用到项目中实现需求,做个记录,以便将来需要,方便查看
链接:
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"><imgsrc="../../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: {//二维码的logodefault: 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"><imgsrc="../../../../../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,建议修改为300useCORS: 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"><imgsrc="../../../../../assets/images/userCard/qrcode_text.png"class="code-img"alt="二维码"/></div></div>
五、恭喜恭喜
恭喜你我又学会了新的东西,真棒呀真棒呀,祝你我今天开心呐,有问题请留言,看见就会回的,不过不一定会。