前言
需求背景:根据table中的数据,下载对应的二维码,并需在二维码下方添加编号和地址。实现效果如下图↓
一、实现思路
- 通过
qrcodejs2
插件生成二维码 - 通过
html2canvas
插件对页面指定区域进行图片生成 - 通过
JSZip
插件对生成的图片进行压缩 - 通过
FileSaver
插件对生成的图片进行导出成压缩文件格式!
二、下载相应库
import QRCode from 'qrcodejs2';
import html2canvas from "html2canvas"; //生成图片
import JSZip from "jszip"; //文件压缩
import FileSaver from "file-saver"; //导出文件
三、封装代码
- template
代码如下:
<template>
<div ref="html2canvasRef" class="QRCodeBox">
<div :id="id" :ref="id" class="QRCode"></div>
<div v-if="QRCodeInfo.title" class="QRCode_title">{{ QRCodeInfo.title }}</div>
</div>
</template>
- style
代码如下:
.QRCodeBox {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 200px;
height: 200px;
position: fixed;
margin-top: -99999999999999999px;
background: transparent;
.QRCode {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.QRCode_id, .QRCode_title {
margin-bottom: 15px;
font-size: 12px;
}
}
- js
<script>
import QRCode from 'qrcodejs2';
import html2canvas from "html2canvas"; //生成图片
import JSZip from "jszip"; //文件压缩
import FileSaver from "file-saver"; //导出文件
export default {
data() {
return {
qrcode: '',
QRCodeInfo: {},
QRCodeList: []
}
},
props: {
id: {
type: String,
default: "QRCode",
required: true
},
width: {
type: String | Number,
default: 150
},
height: {
type: String | Number,
default: 150
},
colorDark: {
type: String,
default: '#000000'
},
colorLight: {
type: String,
default: '#ffffff'
},
logoUrl: {
type: String,
default: ''
},
zipName: {
type: String,
default: '二维码.zip'
},
isBatchDownload: {
type: Boolean,
default() {
return false
}
}
},
watch: {
QRCodeList(QRCodeList) {
this.list = QRCodeList
}
},
mounted() {
},
methods: {
QRCodeInit(data) {
this.QRCodeInfo = data;
return new Promise((resolve) => {
this.qrcode = new QRCode(this.$refs[this.id], {
text: data.id,
width: this.width,
height: this.height,
colorDark: this.colorDark,
colorLight: this.colorLight,
correctLevel: QRCode.CorrectLevel.H,
margin: 5,
type: "image/png"
});
if (this.logoUrl) {
let canvas = this.qrcode._el.getElementsByTagName("canvas")[0];
let img = this.qrcode._el.getElementsByTagName("img")[0];
let ctx = canvas.getContext("2d");
let logo = new Image();
logo.crossOrigin = "Anonymous";
logo.src = this.logoUrl;
logo.onload = () => {
let codeWidth = (this.width * 0.8) / 2;
let codeHeight = (this.height * 0.8) / 2;
ctx.drawImage(logo, codeWidth, codeHeight, this.width * 0.2, this.height * 0.2);
img.src = canvas.toDataURL();
resolve(this.qrcode);
}
} else {
resolve(this.qrcode);
}
})
},
removeCode() {
if (this.qrcode) {
this.$refs[this.id].innerHTML = ''
}
},
// base64 转 二进制流(blob)
dataURLtoBlob(dataUrl) {
let arr = dataUrl.split(","),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {
type: mime,
});
},
async batchDownload(QRCodeList = []) {
this.QRCodeList = QRCodeList;
const imgList = []; //保存生成图片
for (let i = 0; i < QRCodeList.length; i++) {
await this.QRCodeInit(QRCodeList[i]);
await html2canvas(this.$refs.html2canvasRef, {
backgroundColor: null,
useCORS: true,
allowTaint: true,
scale: 1,
}).then((canvas) => {
this.removeCode(); //图片生成完成时删除图片
let url = canvas.toDataURL("image/png");
if (this.isBatchDownload) {
imgList.push({url, name: QRCodeList[i].title});
//判断当生成的图片和要生成的数据长度相等时调用压缩函数
if (imgList.length === QRCodeList.length) {
this.imageCompress(imgList);
}
} else {
const time = new Date().getTime();
const title = `${time} -【${QRCodeList[i].title}】二维码.png`;
let a = document.createElement("a");
a.href = url;
a.download = title;
a.click();
}
}).catch(err => {
console.log(err)
});
}
},
// 压缩转码
imageCompress(imgList) {
let zip = new JSZip();
let index = 0;
for (let i = 0; i < imgList.length; i++) {
index++;
let blob = this.dataURLtoBlob(imgList[i].url); //转二进制
const time = new Date().getTime();
const title = `${time} -【${imgList[i].name}】二维码.png`;
zip.file(title, blob, {blob: true});
if (index === imgList.length) {
zip.generateAsync({type: "blob"}).then(
(blob) => {
FileSaver.saveAs(blob, this.zipName);
}
).catch(() => {
});
}
}
},
},
}
四、效果
-
单个下载
-
批量下载