需要:批量下载价签,点击批量下载,if 抉择一条数据则绘制一张 canvas,并且间接下载。else 多条数据则循环绘制多张 canvas,并且下载 zip,zip 名字设置“标签”+ 以后日期(zip 名字可自行设置)
此性能我用的 vue 实现的,然而 canvas 绘制海报的原理都是一样的。
知识点:革除画布,画矩形、画边框、截取图片画图、文字超出换行并显示省略号、字体大小色彩加粗、1px 线条、循环生成 canvas 并且下载、下载 zip
留神的点:
- 图片加载的时候会提早绘图的过程 Canvas 期待所有图片加载实现才开始绘图, 此处用的是 promise.all() 解决,留神同步异步得问题。(https://www.cnblogs.com/jannr…
<template>
<div>
<el-button type="text" @click="handleLabelDownload""> 批量下载 </el-button>
<canvas ref="canvas" width="400" height="916" style="display:none"></canvas>
<a ref='aImg' href=""></a>
</div>
</template>
<script>
import JSZip from "jszip";
import FileSaver from 'file-saver'
const imgName = require('@/../static/img/ 图片名字.png')
export default {
methods:{
// 点击批量下载按钮 事件 events
async handleLabelDownload(){if(this.items.length !== 0){let zip = new JSZip()
if(this.items.length === 1){await this.drawCanvas(0)
}else{for(let u in this.items){await this.drawCanvas(u,zip)
}
}
if(this.items.length > 1){zip.generateAsync({ type: 'blob'}).then(function (content) {let date = new Date(),month = 0;
if(date.getMonth() + 1 < 10){month = '0'+(date.getMonth()+1)
}else{month = date.getMonth() +1
}
FileSaver.saveAs(content, '标签 -'+month+'-'+date.getDate()+'.zip');
});
}
}
},
// 加载图片 预加载图片,最初返回一个 promise 对象
loadImage(url) {return new Promise((resolve)=>{const img = new Image();
img.onload = ()=>resolve(img);
img.src = url;
})
},
getTrueLength(str) {
let len = 0, trueLen = 0;
if(str){
len = str.length
for (let x = 0; x < len; x++) {if (str.charCodeAt(x) > 128) {trueLen += 2;} else {trueLen += 1;}
}
}
return trueLen;
},
cutString(str, leng) {
let len = str.length, tlen = len, nlen = 0;
for (let x = 0; x < len; x++) {if (str.charCodeAt(x) > 128) {if (nlen + 2 < leng) {nlen += 2;} else {
tlen = x;
break;
}
} else {if (nlen + 1 < leng) {nlen += 1;} else {
tlen = x;
break;
}
}
}
return tlen;
},
// 绘制 价签
async drawCanvas(u,zip){const {price,itemId,itemName,itemBn,distributor_id,label_name,label_bn,label_spec,label_model,label_texture} = this.items[u]
// 掉接口 去获取二维码 url
const rest = await goodsCode({itemId, itemName,itemBn,distributor_id})
const iconUrl = rest.data.data.qrcode_url || ''
await Promise.all([this.loadImage(this.imgName),
this.loadImage(iconUrl)
]).then((imgs) => {
// 获取画布画笔
const context = this.$refs.canvas.getContext('2d')
// 清理矩形办法:clearRect(x,y,w,h)
context.clearRect(0,0,400,916)
// 背景 框
context.fillStyle = '#ffffff'
context.fillRect(0,0,400,916);
// 描边矩形办法:strokeRect(x,y,w,h)
context.strokeStyle='#32323e';
context.lineWidth=2;
context.strokeRect(0, 0, 400, 916);
// 填充矩形办法:fillRect(x,y,w,h)
context.fillStyle='#32323e';
context.fillRect(1,1, 400,140);
// title 字
context.font = '42px 微软雅黑';
context.textAlign ='center';
context.fillStyle ='#fff';
context.fillText(title 名字,224,84);
// logo
context.drawImage(imgs[0],0,1000,1500,1500,90,49,50,50);
// 商品名称
let text = label_name
if(text){context.beginPath() // 开始绘画的申明
context.font = '40px 微软雅黑';
context.fillStyle ='#373737';
if(this.getTrueLength(text) <= 18){
context.textAlign ='center';
context.fillText(text,200,240);
context.fillText(text,201,240);
}else{for (let i = 1; this.getTrueLength(text) > 0; i++) {let tl = this.cutString(text, 18);
context.textAlign ='left';
if(i <= 2){
let t = 0,s='';
if(i == 2){if(this.getTrueLength(text.substr(0, tl)) >= 16){
t = 8
s='...'
}else{t = tl}
}else{t = tl}
context.fillText(text.substr(0, t).replace(/^\s+|\s+$/, "")+s, 20, i * 45 + 190);
context.fillText(text.substr(0, t).replace(/^\s+|\s+$/, "")+s, 21, i * 45 + 190);
}
text = text.substr(tl);
}
}
context.closePath()}
// 货号
if(label_bn){
context.font = '24px 微软雅黑';
context.fillStyle ='#373737';
context.textAlign ='center';
context.fillText(label_bn,200,323,360);
}
// 线条
context.moveTo(20.5,370.5); // 定义终点, 能够了解为将画笔挪动到一个地位
context.lineTo(20.5,370.5) // 定义一个线条一端的终点
context.lineTo(380.5,370.5) // 定义一个线条一端的起点
context.lineWidth = 1 // 定义线条宽度
context.strokeStyle='#d0d0d0'; // 定义线条色彩
// context.lineCap='round' // 定义线帽(含圆角、尖角、斜角)context.stroke() // 给线条上色,即进行绘制
context.font = '22px 微软雅黑';
context.fillStyle ='#373737';// 文字色彩
context.textAlign ='center';
context.fillText('规格:',53,412); // 文本程度对齐形式
context.fillText('规格:',54,412); // 文字加粗
// 规格值
if(label_spec){
context.font = '18px 微软雅黑';
context.fillStyle ='#373737';
context.textAlign ='left';
context.fillText(label_spec,82,413,300);
}
context.moveTo(20.5,434.5);
context.lineTo(20.5,434.5);
context.lineTo(380.5,434.5);
context.lineWidth = 1
context.strokeStyle='#d0d0d0';
context.stroke();
context.font = '22px 微软雅黑';
context.fillStyle ='#373737';
context.textAlign ='center';
context.fillText('型号:',53,476);
context.fillText('型号:',54,476);
if(label_model){
context.font = '18px 微软雅黑';
context.fillStyle ='#373737';
context.textAlign ='left';
context.fillText(label_model,82,477,300);
}
context.moveTo(20.5,498.5);
context.lineTo(20.5,498.5);
context.lineTo(380.5,498.5);
context.lineWidth = 1
context.strokeStyle='#d0d0d0';
context.stroke();
context.font = '22px 微软雅黑';
context.fillStyle ='#373737';
context.textAlign ='center';
context.fillText('材质:',53,540);
context.fillText('材质:',54,540);
if(label_texture){
context.font = '18px 微软雅黑';
context.fillStyle ='#373737';
context.textAlign ='left';
context.fillText(label_texture,82,541,300);
}
context.moveTo(20.5,562.5);
context.lineTo(20.5,562.5);
context.lineTo(380.5,562.5);
context.lineWidth = 1
context.strokeStyle='#d0d0d0';
context.stroke();
// 价格
context.font = '30px 微软雅黑';
context.fillStyle ='#373737';
context.textAlign ='center';
const prices = '¥' + price
context.fillText(prices,200,662);
context.fillText(prices,201,662);
context.moveTo(20,692);
context.lineTo(20,692);
context.lineTo(380,692);
context.lineWidth = 1
context.strokeStyle='#a3a3a3';
context.stroke();
context.moveTo(20,697);
context.lineTo(20,697);
context.lineTo(380,697);
context.lineWidth = 1
context.strokeStyle='#a3a3a3';
context.stroke();
context.drawImage(imgs[1],140,730,130,130);
context.font = '14px 微软雅黑';
context.textAlign ='center';
context.fillStyle ='#373737';
context.fillText('扫 码 了 解 更 多',200,880);
if(!zip){
// 如果是一张图片的话,就间接主动触发 a 标签的 click 事件,主动下载文件
let dataURL = this.$refs.canvas.toDataURL();
let oA = this.$refs.aImg;
oA.href = dataURL;
oA.download = name + '.png'; // 下载的文件名能够此处批改
oA.click()}
})
if(zip){await this.addToZip(this.$refs.canvas, zip, name+'.png');
}
},
addToZip(canvas, zip, name){return new Promise((resolve, reject) => {canvas.toBlob(function (blob) {zip.file(name, blob);
resolve();});
})
},
}
}
</script>
实际效果: