使用jsPDF+html2canvas导出PDF文件分页--可添加上下页边距

avatar
作者
猴君
阅读量:0

一、常规思路

想要将html页面通过pdf文件导出,一般我们使用html2canvas+jsPDDF导出。
单纯使用jsPDF的html()方法要求导入全部字体,于是转换思路,先转成canvas,在通过贴图,贴到pdf中,代码如下:

安装:

npm html2canvas npm jspdf 

引入:

import html2canvas from 'html2canvas'; import jsPDF from 'jsPDF';  

具体代码:

// 生成pdf文件流 const elem =document.getElementById('reportContent'); const canvas = await html2canvas(elem!);     //以下是分页 // pdf的尺寸 const pdfWidth = canvas.width; //a4页面尺寸高比宽为1.414 const pdfHeight = pdfWidth * 1.414; let pageHeight = canvas.height; let position: number = 0; //贴图的宽高 const imgWidth = canvas.width; const imgHeight = imgWidth / canvas.width * canvas.height; //将canvas标签转化为base64码 const pageData = canvas.toDataURL('image/jpeg', 2.0); //创建pdf对象 const pdf = new jsPDF('p', 'pt', [pdfWidth, pdfHeight]); if(pageHeight < pageHeight) {     pdf.addImage(pageData, 'JPEG', 0, 0,imgWidth,imgHeight); } else {     while(pageHeight > 0) {         pdf.addImage(pageData, 'JPEG', 0, position,imgWidth,imgHeight);         position -= pdfHeight ;         pageHeight -= pdfHeight;         if(pageHeight > 0) {             //如果图片还没有贴完,继续添加pdf页             pdf.addPage();         }     } } //如果不需要直接下载,需要pdf的blob文件流,使用output const pdfBlob = pdf.output('blob'); //直接下载为pdf文件 pdf.save() 

参考:https://www.zhangxinxu.com/wordpress/2023/06/js-canvas-jspdf-export-pdf/

但是以上的方案,导出来的pdf页,每页是直接顶满,上下没有页边距,如下图:
在这里插入图片描述

想要添加上下页边距怎么弄呢?

二、通过裁剪canvas贴图

思路:将canvas进行裁剪,每页裁剪的高度,比pdf的页小一点,剩下的留为页边距
上代码:

//创绘制切割后绘制canvas用的canvas标签以及对应的context对象 const perCanvas = document.createElement('canvas'); perCanvas.style.backgroundColor = '#fff' const context  = perCanvas.getContext('2d');   // 将需要下载的html标签转成canvas标签,并获取对应的base64码 const elem =document.getElementById('reportContent'); const canvas = await html2canvas(elem!); const canvasData = canvas.toDataURL('image/jpeg', 1.0);   // pdf的尺寸 const pdfWidth = canvas.width; const pdfHeight = pdfWidth * 1.414;   //切割后的canvas图片的宽高,就等于每页pdf的宽高 perCanvas.width = canvas.width; perCanvas.height = pdfHeight;   // 每张图片的高度:适当减少100,上下各留50页边距 const perHeight = pdfHeight - 100;   // 计算切割次数 let splitCount = Math.ceil(canvas.height / perHeight); if(splitCount * perHeight < canvas.height) splitCount++;   //创建img对象,加载完整的canvas图片 const img = new Image(); img.src = canvasData;   //创建pdf对象 const pdf = new jsPDF('p', 'pt', [pdfWidth, pdfHeight]); //待图片加载完成 await setTimeout(() => {}, 5000)   //切割canvas图片,贴到每一页pdf中 for (let i = 0; i < splitCount; i++) {     const startY = i * perHeight; // 起始y坐标       // 清空画布     context!.clearRect(0, 0, perCanvas.width, pdfHeight);     context!.fillStyle = '#fff';     context!.fillRect(0, 0, perCanvas.width, pdfHeight);     // 绘制当前切割区域的图片     context!.drawImage(img, 0, startY, perCanvas.width, perHeight, 0, 0, perCanvas.width, perHeight);     const perCanvasData = perCanvas.toDataURL('image/jpeg', 1.0);     pdf.addImage( perCanvasData , 'JPEG', 0, 50,perCanvas.width,perCanvas.height);     if(i < splitCount - 1) pdf.addPage(); };   pdf.save(); 

这样导出的每一页pdf都留有上下页边距,如图:
在这里插入图片描述

三、遗留问题

不过这两种方式都存在一个问题:内容截断的问题:
有时候刚好分页裁剪时刚好在一行字的正中间,暂时没有解决办法,有待思考,等找到解决方案再来更新。

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!