事情是这么个事情,本来业务就是把一个页面导出pdf,那不是简简单单
网上一查,按照步骤来:
- 安装html2canvas
pnpm install html2canvas --save
- 安装jspdf
pnpm install jspdf --save
然后从网上 Ctrl + c, Ctrl + v
const opt = {
allowTaint: true,
dpi: window.devicePixelRatio, // 提升导出文件的分辨率
scale: 2, // 提升导出文件的分辨率
backgroundColor: 'white',
useCORS: true,
height: dom.scrollHeight,
windowHeight: dom.scrollHeight,
windowWidth: dom.offsetWidth
}
await html2canvas(dom, opt).then(
(canvas) => {
var pdf = new jsPDF('p', 'mm', 'a4') // A4纸,纵向
var ctx: any = canvas.getContext('2d')
var a4w = 190; var a4h = 277 // A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277
var imgHeight = Math.floor(a4h * canvas.width / a4w) // 按A4显示比例换算一页图像的像素高度
var renderedHeight = 0
while (renderedHeight < canvas.height) {
var 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() }// 如果后面还有内容,添加一个空页
}
pdf.save(`${title}.pdf`)
})
}
我天真的以为到这里就结束了,一天窝囊费到手
不出意外的话,果然就出意外了,结果下午测试悄悄对我说:
你的导出有bug
我当时肯定是拒绝的,直接否定三连:不是我,不可能,不存在
心想:网上找的这个导出功能,那是经过广大网友验证的
在测试再三乞求下,勉为其难先看看问题吧
这尼玛不看还好,一看吓一跳, 一个页面查询7天或者30天数据的时候,这NM的页面干到了8W多px的高度,而canvas在不同浏览器是有高度限制的(canvas:这长度,别说我顶不住,隔壁pdf也顶不住啊),难怪特么导出100多页空白(我顶你个肺,什么沙雕设计,导出这么长的页面)
这咋整,对于一个Ctrl党,赶紧去网上找资料吧,找遍了也没找到能导出一个8W加的html页面的EX,原地裂开
没办法自己上吧
写代码前先想想思路, 一个页面8Wpx的高度,canvas都炸了,咋整? 那我们就分多个canvas嘛,那不就好了,既然思路想到了,那就开干,废话不多说直接上代码:
export async function htmlToPDF3(element: HTMLElement, filename = '未命名', callback = () => {}) {
if (!element) {
callback();
return;
}
var a4w = 190; var a4h = 277
const domH = element.scrollHeight;
const domW = element.offsetWidth;
// 设定一个canvas的高度
const pageMax = Math.floor(a4h * domW / a4w) * 10;
const pageNum = Math.ceil(domH / pageMax)
for (let i = 0; i < pageNum; i++) {
await htmlToPDFCanvas(
i,
element,
i * pageMax,
domH - i * pageMax > pageMax ? pageMax : domH - i * pageMax,
domW,
filename
)
}
// 关闭loading
callback()
}
const htmlToPDFCanvas = async (i:number, dom: HTMLElement, positionNum: number, height: number, width: number, filename: string) => {
// 根据高度去绘制canvas
var position: number = positionNum
const opt = {
allowTaint: true,
dpi: window.devicePixelRatio, // 提升导出文件的分辨率
scale: 2, // 提升导出文件的分辨率
backgroundColor: 'white',
useCORS: true,
height,
windowHeight: height,
windowWidth: width,
x: 0,
y: position
}
const canvas = await html2canvas(dom, opt)
.......
参考最上面导出代码
.......
pdf.save(`${filename + i}.pdf`)
}
饮水思源, 注:(总不能天天Ctrl各位大佬的,也把现成的丢这给各位兄弟们直接Ctrl)
注(当然也可以循环的时候丢到一个pdf里面然后导出,页面高度正常的时候是没有问题的,但是过高(像我这个8Wpx的页面),pdf的长度也超了!)
参考文档:使用jsPDF导出PDF文件实践分享 等