告别懒癌,对最近做的事情做一些记录。
vue-qr,canvas,JSZip,FileSaver前端隐式生成二维码合成海报打包压缩保存到本地
下载引入:
import vueQr from 'vue-qr';
import JSZip from 'jszip'
import FileSaver from 'file-saver';
//注意图片引入方式
import posterBgImg from "@/assets/img/activation_base.jpg";
import qrcodeLogo from "@/assets/img/logo.png";
注册组件,图片和一些数据:
components: {
vueQr,
},
data:{
posterSize: 1594/827,// 海报高宽比例
qrCodeSize: {// 二维码与海报对应比例 =》 用于设置二维码在海报中的位置
width: 300/827,
height: 300/1594,
left: 261/827,
top: 612/827
},
poster: '',// 合成图片
nowUrl:'',
zip:'',
imgZipList:'',
countImg:0,
batchNo:'',
batchOrpage:''
list: [],
//注意图片引入方式
posterBgImg,
qrcodeLogo,
},
computed: {
//手机端兼容的,根据屏幕宽度设置海报尺寸
screenWidth(){
let w = document.body.clientWidth || document.documentElement.clientWidth || 375;
return w > 480 ? 480 : w ;
}
},
HTML部分,二维码生成:最重要的三个属性
ref:命名。方便以后this.{id}`].$el.src 拿到生成的二维码地址
text:就是二维码的信息啦,扫描后打开的网页。
size:尺寸
更多参数可以看文档根据需求选择不多赘述
我的项目里是批量生成的,最多支持一百张,没有太大压力。 并且全v-show=false隐藏也并不影响生成和下载功能。
//单张二维码
<vue-qr :ref="'qr'+scope.row.id" :text="scope.row.url" :size="300" v-show=false></vue-qr>
//批量二维码
<el-table
v-loading="listLoading"
:data="List"
element-loading-text="加载中..."
border
fit
highlight-current-row
:header-cell-style="{background:'#f4f0ec',color:'#000000'}"
style="margin:20px 0;"
v-show="false"
>
<el-table-column label="" min-width="60" align="center" >
<template slot-scope="scope">
<vue-qr v-show="false" :ref="'qr'+scope.row.id" :text="scope.row.url" :size="300"></vue-qr>
</template>
</el-table-column>
</el-table>
直接贴代码吧。因为需求从拼接海报改成不拼接海报,所以没有做合并。
这部分是最终版本:
下载单张纯二维码——直接使用qrcode提供的方法dispatchEvent。
批量打包压缩下载纯二维码的代码——
//下载单张纯二维码,是vue-qr提供的方法
downLoadPureCode(id,batchNo,code){
let a = document.createElement('a');
// 下载图命名
a.download = `二维码_${code}`;
// 二维码url
a.href = this.$refs['qr'+`${id}`].$el.src;
//下载
a.dispatchEvent(new MouseEvent('click'))
},
//压缩下载单页面全部纯二维码
downLoadPagePureCode(){
this.batchOrpage='page'
//创建一个code文件夹,文件里里创建一个images文件,文件内容为空
this.zip = new JSZip()
this.imgZipList = this.zip.folder("images")
//遍历数组拿
this.list.forEach(item=>{
// console.log('绘制',item.id)
let a = document.createElement('a'+item.code);
//拿到所有需要加入压缩包的二维码图片地址
a.href = this.$refs['qr'+`${item.id}`].$el.src;
// 打zip
let that=this
that.countImg++
// console.log('push第'+that.countImg,a.href)
let total= that.list.length
//↓第一个参数是单张二维码图片的命名,第二个参数是二维码的base64,这里用replace把URL的前缀截掉仅保留纯base64编码,可以地址栏打开的那种
that.imgZipList.file('二维码_'+item.code+'.png', a.href.replace(/^data:image\/(png|jpg);base64,/, ""), {base64: true});
// console.log('push第'+that.countImg+'succ')
if(that.countImg == total){
// console.log('finish')
//添加完下载
this.zip.generateAsync({type:"blob"}).then(function(content) {
// 使用file-saver保存下载zip文件,第二个参数是压缩包命名
FileSaver.saveAs(content, `第${that.queryWord.pageIndex}页_二维码.zip`);
});
this.countImg=0
}
})
},
下面这部分是最初做的,相比之前就是在调用了combinedPoster方法拼接二维码和背景图,合成海报。 这个海报是用canvas绘制,同样不在页面展示也可以实现下载。
//下载单张海报
downLoadCode(id,batchNo,code){
let a = document.createElement('a');
a.href = this.$refs['qr'+`${id}`].$el.src;
this.combinedPoster(a.href,batchNo,code,false)
},
//压缩下载页面全部海报
downLoadPageCode(){
this.batchOrpage='page'
//创建一个code文件夹,文件里里创建一个images文件,文件内容为空
this.zip = new JSZip()
this.imgZipList = this.zip.folder("images")
this.list.forEach(item=>{
console.log('绘制',item.id)
let a = document.createElement('a'+item.code);
a.href = this.$refs['qr'+`${item.id}`].$el.src;
this.combinedPoster(a.href,item.batchNo,item.code,true)
})
},
//拼接二维码和背景图,合成海报的方法
//参数依次是,二维码base64,内部批次号,内部编码,是否打zip包
combinedPoster(_url,batchNo,code,ifzip){
let that = this,
posterBgImg = this.posterBgImg; //固定的背景地址
// console.log("open draw: ", posterBgImg, _url)
let base64 = '',
canvas = document.createElement('canvas'),
ctx = canvas.getContext("2d"),
_w = this.screenWidth * 2, // 图片宽度
_h = this.posterSize * _w, // 图片高度
_qr_w = this.qrCodeSize.width * _w, // 二维码宽 = 比例 * 宽度
_qr_h = this.qrCodeSize.height * _h, // 二维码高 = 比例 * 高度
_qr_t = this.qrCodeSize.top * _w, // 二维码顶部距离 = 比例 * 宽度
_qr_l = this.qrCodeSize.left * _w; // 二维码左侧距离 = 比例 * 宽度
// 设置canvas宽高
canvas.width = _w;
canvas.height = _h;
ctx.rect(0, 0, _w, _h);
ctx.fillStyle = '#fff'; // 填充颜色
ctx.fill();
// 迭代生成: 第一层(底图)+ 第二层(二维码)
// file:文件,size:[顶部距离,左侧距离,宽度,高度]
let _list = [
{
file: posterBgImg,
size: [0, 0, _w, _h]
}, {
file: _url,
size: [_qr_l, _qr_t, _qr_w, _qr_h]
}
];
// 开始绘画
let drawing = (_index) => {
// 判断当前索引 =》 是否已绘制完毕
if (_index < _list.length) {
// 等图片预加载后画图
let img = new Image(),
timeStamp = new Date().getTime();
// 防止跨域
img.setAttribute('crossOrigin', 'anonymous')
img.src = _list[_index].file
img.onload = function() {
// 画图
ctx.drawImage(img, ..._list[_index].size)
// 递归_list
drawing(_index + 1)
}
} else {
// 生成图片
base64 = canvas.toDataURL("image/png")
if (base64) {
// 赋值相应海报上
this.$set(that, 'poster', base64)
if(!ifzip){
//单张下载
if(this.poster){
let a = document.createElement("a");
a.setAttribute("download", "二维码"+'_'+code);
a.href = this.poster
a.click()
}else{
console.log("海报不存在,请重新生成!")
}
}else {
// 打包下载,打zip
that.countImg++
console.log('push第'+that.countImg)
let total=that.list.length
that.imgZipList.file('二维码_'+code+'.png', this.poster.replace(/^data:image\/(png|jpg);base64,/, ""), {base64: true});
console.log('push第'+that.countImg+'succ')
console.log(total)
if(that.countImg == total){
console.log('finish')
//添加完下载
this.zip.generateAsync({type:"blob"}).then(function(content) {
// 使用file-saver保存下载zip文件
if(that.batchOrpage=='batch'){
FileSaver.saveAs(content, `${that.batchNo}_二维码.zip`);
}else{
FileSaver.saveAs(content, `第${that.queryWord.pageIndex}页_二维码.zip`);
}
});
this.countImg=0
}
}
}
}
}
drawing(0)
},