需要:批量下载价签,点击批量下载,if抉择一条数据则绘制一张canvas,并且间接下载。else多条数据则循环绘制多张canvas,并且下载zip,zip名字设置“标签”+以后日期(zip名字可自行设置)
此性能我用的vue实现的,然而canvas绘制海报的原理都是一样的。
知识点: 革除画布,画矩形、画边框、截取图片画图、文字超出换行并显示省略号、字体大小色彩加粗、1px线条、循环生成canvas并且下载、下载zip
留神的点:

  1. 图片加载的时候会提早绘图的过程 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>

实际效果: