qrcode+jspdf前端打印标签
业务背景
需求是前端打印出一排2个、一排5个、圆标签等,各种样式的标签,并包含二维码、中英文、数字, 如下图:
对于打印机来讲,一排就是一页,想要打印出这样的标签,步骤如下:
确认前端打印功能
计算每个标签在一页中的位置
每个标签中打印二维码
打印英文和数字
打印中文
方案确认
首先确定jspdf作为前端打印插件,jspdf的文档很细,功能强大,是一个优秀的框架,但是默认不支持中文,需要额外引入字体,最开始想通过html2canvas的方法把页面的中文通过dom生成图片再使用jspdf打印出来的方案,后来发现打印出来的文字很不清晰,清晰度的问题难以解决,所以就只能换成直接使用jspdf直接生成文字的方式处理,就是必须要引入字体文件。
实现方法
一、引入jspdf和qrcode
// 下载包, 本文使用jspdf@2.3.1 npm install jspdf qrcode // 引入 import jsPDF from 'jspdf' var QRcode = require('qrcode') 复制代码
二、确定标签尺寸和纸张尺寸, 配置jspdf
以一排5个为例,使用的纸张尺寸是87 * 33, 标签尺寸是 15 * 30
const pdf = new jsPDF('l', 'mm', [870, 330]) // 声明一套配置 const printConfig = { pageWidth: 870, // 一页宽度 pageHeight: 330, // 一页的高度 left: 35, // 标签左边距 offsetLeft: 174, // 每个标签的偏移量 top: 25, // 标签上间距 picWidth: 100, // 二维码宽度 picHeight: 100, // 二维码高度 linePicNum: 5, // 一排显示个数 rotateDeg: 270, // 角度 fontSize: 58 // 字号 } 复制代码
三、生成二维码并在指定位置打印
const imageList = [] // 声明一个imageList用了存放二维码base64 list.map((item, index) => { QRCode.toDataURL(item.code) .then(url => { imageList.push(url) }) .catch(err => { console.error(err) }) }) // 打印二维码图片 let left = printConfig.left let top = printConfig.top imageList.map(base64 => { left = printConfig.left + printConfig.offsetLeft * (index % printConfig.linePicNum) // 添加图片 pdf.addImage(base64, 'JPEG', left, top, picWidth, picHeight, '', 'FAST') // 超过限制个数就翻页 if (index !== 0 && (index + 1) % printConfig.linePicNum === 0 && index < imageList.length - 1 ) { pdf.addPage([width, height], 'l') } }) 复制代码
这样可以在指定位置打印出二维码了
三、打印英文和数字
jspdf直接可以打印英文和数字,所以直接打印即可, left和top是需要增加偏移量的
pdf.text('this is my word', left + item.offsetLeft, top + item.offsetTop, {angle: printConfig.rotateDeg}) 复制代码
四、打印中文
中文的引入会麻烦一些,需要引入语言包,具体生成方法可以参考官网,或参考 www.cnblogs.com/ww01/p/1149…
先找到ttf文件后convert成一个js,将生成的js放到文件中
function addfont(pdf) { var font = 'AA****' // 中的就是ttf转化成的编码 pdf.addFileToVFS('bolds', font) return true; } // 在pdf生成后,添加并设置字体 addfont(pdf) pdf.addFont('bolds', 'customFont', 'normal') pdf.setFont('customFont') pdf.setFontSize(58) //打印 pdf.text('我是中文', left + item.offsetLeft, top + item.offsetTop, {angle: printConfig.rotateDeg}) 复制代码
完整代码
以下是我封装的打印方法, 外部直接调用generatePrint即可
import jsPDF from 'jspdf' var QRCode = require('qrcode') let width, height; let pdf; let timer class PrintTag { constructor(data) { this.imageList = [] this.list = data this.printConfig = { pageWidth: 870, // 一页宽度 pageHeight: 330, // 一页的高度 left: 35, // 标签左边距 offsetLeft: 174, // 每个标签的偏移量 top: 25, // 标签上间距 picWidth: 100, // 二维码宽度 picHeight: 100, // 二维码高度 linePicNum: 5, // 一排显示个数 rotateDeg: 270, // 角度 fontSize: 58 // 字号 } this.setPdfConfig() } start() { this.buildQRcode() } // 设置pdf setPdfConfig() { width = this.printConfig.pageWidth height = this.printConfig.pageHeight pdf = new jsPDF('l', 'mm', [width, height]) //添加并设置字体 addfont(pdf) pdf.addFont('bolds', 'customFont', 'normal') pdf.setFont('customFont') pdf.setFontSize(58) } // 生成二维码 buildQRcode() { this.list.map((item, index) => { QRCode.toDataURL(item.sampleIdLims) .then(url => { this.imageList.push(url) }) .catch(err => { console.error(err) }) }) this.checkImageLoaded() } // qrcode是异步,所以延迟生成pdf checkImageLoaded() { setTimeout(() => { if (this.imageList.length === this.list.length) { this.generate(this.imageList) } }, 500) } // 生成pdf generate(arr) { console.time('print') const picWidth = this.printConfig.picWidth const picHeight = this.printConfig.picWidth let left = 0 let top = this.printConfig.top const textOpt = {angle: this.printConfig.rotateDeg} arr.map((base64, index) => { left = this.printConfig.left + this.printConfig.offsetLeft * (index % this.printConfig.linePicNum) pdf.addImage(base64, 'JPEG', left, top, picWidth, picHeight, '', 'FAST') pdf.text('hello 12345', left + item.offsetLeft, top + item.offsetTop, textOpt) pdf.text('我说中文', left + item.offsetLeft, top + item.offsetTop + 25, textOpt) if (index !== 0 && (index + 1) % this.printConfig.linePicNum === 0 && index < arr.length - 1 ) { pdf.addPage([width, height], 'l') } }) window.open(pdf.output('bloburl'), '_blank'); console.timeEnd('print') } } export function generatePrint(data, step, lableType) { console.log(data, step) return new PrintTag(data, step, lableType).start() }
作者:上头小官
链接:https://juejin.cn/post/7023680840441790501