JS - PDF文件生成库jsPDF使用详解5(将html页面导出为pdf)
六、将 html 页面导出为 pdf
1,将页面上的指定元素导出成 pdf
(1)下面样例代码中,我们页面上有一个 ul 列表。当页面打开时,自定将这个 ul 列表转换成 pdf 并导出。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="jquery-3.1.1.js" charset="utf-8"></script> <script src="jspdf.min.js" charset="utf-8"></script> <script type="text/javascript"> //页面初始化 function init() { var doc = new jsPDF(); //自定义渲染器(决定哪些元素需要渲染) var specialElementHandlers = { '#editor': function(element, renderer){ return true; } }; //设置边距(pdf文档中) var margins = { top: 20, bottom: 60, left: 20, width: 522 }; //获取指定html页面元素来生成pdf文件 doc.fromHTML($('ul').get(0), margins.left, //内容起点的x坐标 margins.top, //内容起点的y坐标 { 'width': margins.width, //内容在pdf里的最大宽度 'elementHandlers': specialElementHandlers }, function (dispose) { doc.save('Test.pdf'); }, margins); } </script> </head> <body onload="init()"> <ul> <li>welcome to hangge.com</li> <li>welcome to hangge.com</li> <li>welcome to hangge.com</li> </ul> </body> </html>
2,将整个页面导出成 pdf
如果想要将整个 html 页面的所有元素都导出,只需修改一行代码。
//...... //将整个html页面导出生成pdf文件 doc.fromHTML($('body').get(0), margins.left, //内容起点的x坐标 margins.top, //内容起点的y坐标 //.......
附:结合 html2canvas 实现 html 页面导出成 pdf(支持多页)
当 html 页面内容比较复杂时,我们使用上面的方式导出后会发现里面内容格式都发生了变化。如果想让 pdf 内容结果与原页面一致,我们可以借助 html2canvas 对整个网页或局部内容进行截图,然后再将该截图导出成 pdf。
注意:这里所说的截图并不是真的截图,而是通过遍历页面 DOM 结构,收集所有元素信息及相应样式,渲染出 canvas image。然后我们使用这个 canvas image 导出 pdf
1,html2canvas 配置
(1)首先我们到其官网地址将 html2canvas.js 下载到我们的项目中来。
(2)然后在页面中将其引用进来即可。
<script src="html2canvas.js" charset="utf-8"></script>
2,生成单页的 pdf
(1)如果网页内容比较少,刚好一个 pdf 页面就可以显示全的话,那么实现起来比较简单。样例代码如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="jspdf.min.js" charset="utf-8"></script> <script src="html2canvas.js" charset="utf-8"></script> <script type="text/javascript"> //页面初始化 function init() { //将整个页面转成canvas html2canvas(document.body).then(canvas => { //返回图片dataURL,参数:图片格式和清晰度(0-1) var pageData = canvas.toDataURL('image/jpeg', 1.0); //方向默认竖直,尺寸ponits,格式a4[595.28,841.89] var doc = new jsPDF('', 'pt', 'a4'); //addImage后两个参数控制添加图片的尺寸,此处将页面高度按照a4纸宽高比列进行压缩 doc.addImage(pageData, 'JPEG', 0, 0, 595.28, 592.28/canvas.width * canvas.height ); doc.save('Test.pdf'); }); } </script> </head> <body onload="init()"> <h2>条目1</h2> <p> 欢迎访问hangge.com 欢迎访问hangge.com 欢迎访问hangge.com 欢迎访问hangge.com </p> <img src="./images/img1.jpg"> <h2>条目2</h2> <p> 欢迎访问hangge.com 欢迎访问hangge.com 欢迎访问hangge.com 欢迎访问hangge.com </p> <img src="./images/img1.jpg"> <h2>条目3</h2> <p> 欢迎访问hangge.com 欢迎访问hangge.com 欢迎访问hangge.com 欢迎访问hangge.com </p> <img src="./images/img1.jpg"> <h2>条目4</h2> <p> 欢迎访问hangge.com 欢迎访问hangge.com 欢迎访问hangge.com 欢迎访问hangge.com </p> <img src="./images/img1.jpg"> </body> </html>
(2)导出结果如下:
3,生成多页的 pdf(自动分页)
(1)如果网页内容比较多,只导出单页的 pdf 的话,那么多余的部分就会被自动截断无法显示。这就需要将内容自动拆分成多页导出。
(2)而实现内容分页的方法比较取巧。我们不必针对每页内容专门生成一个 canvas,而是统一都使用一个完整页面的 canvas。即每一页 pdf 上显示的图片其实是相同的,只不过我们通过调整图片的位置,让每一页显示它需要显示的部分,从而产生了分页效果。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="jspdf.min.js" charset="utf-8"></script> <script src="html2canvas.js" charset="utf-8"></script> <script type="text/javascript"> //页面初始化 function init() { //将整个页面转成canvas html2canvas(document.body).then(canvas => { var contentWidth = canvas.width; var contentHeight = canvas.height; //一页pdf显示html页面生成的canvas高度; var pageHeight = contentWidth / 592.28 * 841.89; //未生成pdf的html页面高度 var leftHeight = contentHeight; //页面偏移 var position = 0; //a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高 var imgWidth = 595.28; var imgHeight = 592.28/contentWidth * contentHeight; var pageData = canvas.toDataURL('image/jpeg', 1.0); var doc = new jsPDF('', 'pt', 'a4'); //有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89) //当内容未超过pdf一页显示的范围,无需分页 if (leftHeight < pageHeight) { doc.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight ); } else { while(leftHeight > 0) { doc.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight) leftHeight -= pageHeight; position -= 841.89; //避免添加空白页 if(leftHeight > 0) { doc.addPage(); } } } doc.save('Test.pdf'); }); } </script> </head> <body onload="init()"> <h2>条目1</h2> <p> 欢迎访问hangge.com 欢迎访问hangge.com 欢迎访问hangge.com 欢迎访问hangge.com </p> <img src="./images/img1.jpg"> <h2>条目2</h2> <p> 欢迎访问hangge.com 欢迎访问hangge.com 欢迎访问hangge.com 欢迎访问hangge.com </p> <img src="./images/img1.jpg"> <h2>条目3</h2> <p> 欢迎访问hangge.com 欢迎访问hangge.com 欢迎访问hangge.com 欢迎访问hangge.com </p> <img src="./images/img1.jpg"> <h2>条目4</h2> <p> 欢迎访问hangge.com 欢迎访问hangge.com 欢迎访问hangge.com 欢迎访问hangge.com </p> <img src="./images/img1.jpg"> <h2>条目5</h2> <p> 欢迎访问hangge.com 欢迎访问hangge.com 欢迎访问hangge.com 欢迎访问hangge.com </p> <img src="./images/img1.jpg"> <h2>条目6</h2> <p> 欢迎访问hangge.com 欢迎访问hangge.com 欢迎访问hangge.com 欢迎访问hangge.com </p> <img src="./images/img1.jpg"> <h2>条目7</h2> <p> 欢迎访问hangge.com 欢迎访问hangge.com 欢迎访问hangge.com 欢迎访问hangge.com </p> <img src="./images/img1.jpg"> <h2>条目8</h2> <p> 欢迎访问hangge.com 欢迎访问hangge.com 欢迎访问hangge.com 欢迎访问hangge.com </p> <img src="./images/img1.jpg"> </body> </html>
(3)导出结果如下:
4,设置左右边距
(1)如果觉得导出的 pdf 中内容紧贴着左侧不好看,想要在左右两边留个边距,只需参考如下高亮部分进行修改即可。
<script type="text/javascript"> //页面初始化 function init() { //将整个页面转成canvas html2canvas(document.body).then(canvas => { var contentWidth = canvas.width; var contentHeight = canvas.height; //一页pdf显示html页面生成的canvas高度; var pageHeight = contentWidth / 592.28 * 841.89; //未生成pdf的html页面高度 var leftHeight = contentHeight; //页面偏移 var position = 0; //a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高 var imgWidth = 555.28; //左右边距20 var imgHeight = 555.28/contentWidth * contentHeight; //左右边距20 var pageData = canvas.toDataURL('image/jpeg', 1.0); var doc = new jsPDF('', 'pt', 'a4'); //有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89) //当内容未超过pdf一页显示的范围,无需分页 if (leftHeight < pageHeight) { doc.addImage(pageData, 'JPEG', 20, 0, imgWidth, imgHeight ); //左右边距20 } else { while(leftHeight > 0) { doc.addImage(pageData, 'JPEG', 20, position, imgWidth, imgHeight) //左右边距20 leftHeight -= pageHeight; position -= 841.89; //避免添加空白页 if(leftHeight > 0) { doc.addPage(); } } } doc.save('Test.pdf'); }); } </script>
(2)导出结果如下: