目录
一、需求背景
二、实现策略
三、基础实现
四、功能完善
五、效果演示
六、总结
一、需求背景
网页作为一种关键的信息传递媒介,承载着丰富多样的内容形态,包括但不限于文本、图像、表格及多媒体元素。然而,网页内容的动态性和不稳定性使得用户在面临长期存储或频繁查阅需求时面临挑战。
为应对这一问题,将网页内容转化为PDF文件不失为一种有效的解决方案。PDF格式具备跨操作系统、跨设备兼容性以及良好的防篡改特性,能确保网页内容的原始状态与完整性得到忠实保留。
通过将整个网页或特定区域转换为PDF,用户可以在任何环境下便捷地访问已保存的网页信息,无论是在离线状态下还是需要长期归档时,都能轻松查阅所需内容。这种转换方式不仅提升了个人用户的资料管理效率,也为学术研究者、数据分析员等专业人士提供了更高效、规范化的资料整理手段。
图 1-示例网页(Vue3+ElementPlus)
二、实现策略
实现网页到PDF的纯前端转换,可遵循以下两种主要路径(以图 1-示例网页为例):
1. 利用浏览器内置功能
现代Web浏览器如Chrome、Firefox等已内置网页打印至PDF的功能。用户仅需打开待保存的网页,通过浏览器的打印对话框选择“另存为PDF”选项,即可将当前视窗中的网页内容直接导出为PDF文件。此方法操作简便,无需额外安装任何软件或插件,适合普通用户快速完成单次或临时性的网页保存任务。
图 2-Chrome浏览器pdf保存功能
浏览器内置的网页保存为PDF功能使用较为便捷,且跨平台兼容,大多数现代浏览器(如Google Chrome、Firefox、Safari、Microsoft Edge等)均支持这一功能,使得用户无论在Windows、macOS、Linux都能轻松实现网页到PDF的转换。但复杂的CSS样式、JavaScript动态生成的内容可能无法完全保留在PDF中,导致转换结果与原网页存在差异。
2. 应用第三方库与工具
对于需要更精细控制、定制化转换效果或集成至特定Web应用程序的场景,可选用专门的JavaScript库或工具进行网页至PDF的转换。这类工具通常提供丰富的配置选项以适应不同需求,如样式定制、页面布局调整等。开发者可将它们无缝嵌入自己的前端项目,通过调用提供的API接口实现在浏览器直接生成PDF文件。
以下是几个常用的前端工具库及其特点:
● jspdf:这是一个广泛应用的JavaScript库,支持在浏览器端直接生成PDF文档。用户可利用其API创建PDF页面、添加文本、图片、图形等元素,最后输出为PDF格式。尽管jspdf在处理简单PDF生成任务时表现出色,但对于复杂的网页布局和样式转换可能需要额外的处理逻辑辅助。
● html2canvas:作为一款强大的HTML转canvas库,html2canvas能够在浏览器环境中实时捕获并渲染网页内容为canvas对象,实现类似截图的效果。其生成的图片质量高,适应性强,尤其在移动端H5场景中用于生成分享图片时表现卓越。由于其易用性和高效性,html2canvas已成为众多开发者在网页截图需求上的首选工具。
● html2pdf:该库专为将HTML内容转化为PDF而设计,基于HTML5和CSS3进行渲染,能够精准保留源网页的样式和布局信息。其API简洁明了,使得前端开发者能够轻松地将任意HTML内容封装为PDF文档。
● pdfmake:这是一个功能强大的PDF文档生成库,支持在客户端与服务器端构建复杂的PDF文档,包括自定义页面布局、表格、列表、图片以及字体和样式。尽管其核心功能侧重于动态创建PDF文档,但同样适用于将HTML内容转为PDF。
针对具体项目需求与技术栈,开发者可灵活选取合适的第三方工具进行网页到PDF的转换实现。
三、基础实现
对于结构简单的网页,直接借助浏览器内置功能或第三方库将整个页面转换为PDF通常可以满足需求。以下以示例网页为例,说明如何利用html2canvas(https://html2canvas.hertzen.com/)与jspdf(https://github.com/parallax/jsPDF)这两个库将其内容输出为PDF文件:
1. 获取待转换元素:首先通过document.getElementById获取待转换的DOM元素。
letelement = document.getElementById("element-to-print");
2. 将元素转换为canvas:调用html2canvas函数,传入目标元素,并设置相关配置项(如允许跨域、画布X/Y坐标等),等待返回转换后的canvas对象。
letcanvas = awaithtml2Canvas(element, {
allowTaint: true,
scrollY: 0,
scrollX: 0,
useCORS: true
});
图 3-html2canvas部分配置项
3. canvas转为图片数据:利用canvas的toDataURL方法将canvas内容转化为指定格式(如PNG)的图片数据。
letpageData = canvas.toDataURL("image/png");
4. 将图片数据写入PDF:初始化一个jsPDF实例,设定纸张大小为A4,并使用addImage方法将图片数据插入PDF文档。该方法接受图片数据、格式、坐标(x, y)、尺寸(width, height)以及可选的别名、压缩比和旋转角度等参数。
// 新建一个pdf
letPDF = new jsPDF(undefined, "pt", "a4");
/**
* pdf.addImage(image, format, x, y, width, height, alias, compression, rotation)
* image:待插入的图片数据
* format:待插入的图片格式,'JPEG', 'PNG', 'GIF', 'BMP'等
* x:图片铺设在PDF中的x轴坐标,单位为pt
* y:图片铺设在PDF中的y轴坐标,单位为pt
* width:图片铺设在PDF中的宽度,单位为pt
* height:图片铺设在PDF中的高度,单位为pt
* alias(可选):图片资源别名
* compression(可选):图片压缩质量,为0-1之间的浮点数
* rotation(可选):图片旋转角度,为0-360之间的整数
*/
// 图片以左边距为20,上边距为30,宽为元素宽,高为元素高的大小添加到PDF中
PDF.addImage(pageData, "png", 20, 30, element.offsetWidth, element.offsetHeight);
// 生成pdf文件
PDF.save("网页.pdf");
四、功能完善
在实际应用中,可能会遇到更复杂的需求和场景,例如:
● 自动分页:为了便于打印,需将PDF按照A4纸尺寸进行合理分页。那么在生成PDF的过程中,需监控图片数据的高度,当其接近或超过一页A4纸的高度时,触发addPage方法添加新页,继续在下一页放置后续图片。
● 元素高度超限处理:对于高度超过一页A4纸的网页元素,如长表格或大型图表,需采取特殊策略。对于可分割的元素(如表格,文章),可以按行或按一定高度阈值拆分为多个子部分,分别插入PDF;对于不可分割的元素,则考虑对其进行适当缩放或分页截取,确保内容能在多页中完整展现,同时保持较好的阅读体验。
// 核心步骤:将图片铺设到pdf页
constaddImage = img=>{
letimgPageWidth = pdfPage.width; // 图片铺设到pdf页上面的宽度,设置为pdf页的可用宽度(即A4纸宽度-左右内边距)
letimgPage = {
width: imgPageWidth, // 图片铺设宽度
height: (img.height / img.width) * imgPageWidth // 图片铺设高度=(图片本身高度/图片本身宽度)*图片铺设宽度
};
// 若图片铺设高度大于一页A4纸高度,则进行二次处理
if(imgPage.height > pdfPage.height) {
// 策略一:图片正常铺设,超出一页纸高度的部分则截断
// pdfPostion:pdf插入内容的位置,初始值为A4纸的上内边距,每插入一张图片,则加上图片的高度
let_pdfPostion = pdfPostion;
// leftImgHeight:待插入图片的高度
letremainingHeight = imgPage.height;
while(remainingHeight > 0) {
pdf.addImage(img.data, "png", padding.width, _pdfPostion, imgPage.width, imgPage.height);
_pdfPostion -= a4Page.height; // 下次铺设的Y轴位置减去一张A4纸的高度
remainingHeight = imgPage.height + _pdfPostion; // 记录此次铺设位置
if(remainingHeight > 0) {
// 大于01,说明还需要再新开一页继续铺设。小于0,则说明待截取图片已铺设完毕
pdf.addPage();
pdfPostion = remainingHeight;
}
}
// 策略二:图片高于一页pdf高度时,将图片按一页高度等比例压缩
// pdf.addPage();
// pdfPostion = padding.height;
// imgPage = {
// width: (img.width / img.height) * pdfPage.height,
// height: pdfPage.height
// };
// let xwidth = (pdfPage.width - imgPage.width) / 2; // 图片居中位移量
// pdf.addImage(img.data, 'png', padding.width + xwidth, pdfPostion, imgPage.width, imgPage.height);
// pdfPostion += imgPage.height;
} else{
// 否则将图片插入到pdf中,若pdf剩余高度不足以插入整张图时,新增一页并将插入位置重置
if(pdfPostion + imgPage.height > pdfPage.height) {
pdf.addPage();
pdfPostion = padding.height;
}
pdf.addImage(img.data, "png", padding.width, pdfPostion, imgPage.width, imgPage.height);
pdfPostion += imgPage.height;
}
};
五、效果演示
以下是当示例网页中表格超高时,对表格采取了分割处理,将表格按行分割成多张图片,生成的pdf:
图 4-超长表格第1页
图 5-超长表格第2页
以下是当网页中包含超长图片时,图片被截断,生成的pdf:
图 6-超长图片第1页
以下是当网页中包含超长图片时,图片被整体缩小,生成的pdf:
图 7-超长图片第2页
六、总结
综上所述,通过利用浏览器内置功能或集成第三方前端库,可有效地将网页内容以纯前端方式转换为PDF文件,满足用户对网页内容长期保存、离线查阅的需求。针对各类复杂场景,则需要选择适当的处理策略,确保生成的PDF文档既符合预期的格式标准,又能再现原始网页信息。
作者:宋安安| 高级前端开发工程师
版权声明:本文由神州数码云基地团队整理撰写,若转载请注明出处。
公众号搜索神州数码云基地,了解更多技术干货。