JS - PDF文件生成库jsPDF使用详解5(将html页面导出为pdf)
作者:hangge | 2018-11-16 08:10
六、将 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)导出结果如下:
全部评论(0)