文章目录
- 最终效果
- 技术依赖包
- 优缺点
- 实现思路
- 代码
最终效果
这个是原页面
这个是前端处理成 pdf
的效果
技术依赖包
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 = true
const dom: any = document.querySelector('#printContent')
const query = this.$route.query
const id = query?.id
if (dom) {
html2canvas(dom).then(async canvas => {
let pdf = new jsPDF('p', 'mm', 'a4') // A4纸,纵向
let ctx: any = canvas.getContext('2d')
let a4w = 190
let a4h = 277 // A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277
let imgHeight = Math.floor((a4h * canvas.width) / a4w) // 按A4显示比例换算一页图像的像素高度
let renderedHeight = 0
while (renderedHeight < canvas.height) {
let page: any = document.createElement('canvas')
page.width = canvas.width
page.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 += imgHeight
if (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)
})
}