需要:批量下载价签,点击批量下载,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>
实际效果:
发表回复