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