文章目录
- 最终效果
- 技术依赖包
- 优缺点
- 实现思路
- 代码
最终效果
这个是原页面
技术依赖包
vue2 + element + html2canvas + jsPDF
html2Canvas 官网
jsPDF 官网
优缺点
- 优点:就是不需要后端处理
pdf
了,原本想着把dom
和css
传递给后端让后端生成,奈何后端是php
,解析器不给力(这是后端跟我讲的,有没有懂php
大佬) - 缺点:生成的
pdf
比较糊,而且表格在分页的时候容易分裂,我暂时没有更好的方案
实现思路
- 将
html
先转换成canvas
,然后生成图片,最后再将图片转换成pdf
- 需要先把页面适配一下
A4
纸张大小,不然下面切割的话会出问题
代码
import html2canvas from 'html2canvas'
import { jsPDF } from 'jspdf'async handleUploadHTMLPDF() {try {this.loading.print = trueconst dom: any = document.querySelector('#printContent')const query = this.$route.queryconst id = query?.idif (dom) {html2canvas(dom).then(async canvas => {let pdf = new jsPDF('p', 'mm', 'a4') // A4纸,纵向let ctx: any = canvas.getContext('2d')let a4w = 190let a4h = 277 // A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277let imgHeight = Math.floor((a4h * canvas.width) / a4w) // 按A4显示比例换算一页图像的像素高度let renderedHeight = 0while (renderedHeight < canvas.height) {let page: any = document.createElement('canvas')page.width = canvas.widthpage.height = Math.min(imgHeight, canvas.height - renderedHeight) // 可能内容不足一页// 用getImageData剪裁指定区域,并画到前面创建的canvas对象中page.getContext('2d').putImageData(ctx.getImageData(0,renderedHeight,canvas.width,Math.min(imgHeight, canvas.height - renderedHeight)),0,0)pdf.addImage(page.toDataURL('image/jpeg', 1.0),'JPEG',10,10,a4w,Math.min(a4h, (a4w * page.height) / page.width)) // 添加图像到页面,保留10mm边距renderedHeight += imgHeightif (renderedHeight < canvas.height) {pdf.addPage() // 如果后面还有内容,添加一个空页}// delete page;}// 保存文件pdf.save('output.pdf')const blob = pdf.output('blob')const base64 = await this.blobToBase64(blob)// 之后想传给后端 blob 或者 base64 随便你})}} catch (err) {console.log(err)}
}
blobToBase64 = (blob: Blob): Promise<string> => {return new Promise(resolve => {const reader = new FileReader()reader.onloadend = () => resolve(reader.result as string)reader.readAsDataURL(blob)})
}