大数跨境
0
0

最前端|还在焦虑网页内容无法保存?一文教你轻松给网页拍照

最前端|还在焦虑网页内容无法保存?一文教你轻松给网页拍照 AI实践工程院
2024-06-13
2
导读:再也不怕内容无法保存了!



神州数码云基地

最前端专栏

纯前端实现网页内容的转换与保存

相信大家在日常的工作和生活中都需要经常访问各类网站来获取信息,然而网页内容的动态性和不稳定性会带来存储和查阅问题。


如果能将网页转换为PDF文件,就可有效解决这些问题,提供跨平台兼容性和内容完整性。


本篇文章从前端角度出发,教你实现网页内容的转换与保存。


 作者 

宋安安 | 高级前端开发工程师

代码无界,学习无涯,每一步都是前进的阶梯


Part1

需求背景


网页作为一种关键的信息传递媒介,承载着丰富多样的内容形态,包括但不限于文本、图像、表格及多媒体元素。然而,网页内容的动态性和不稳定性使得用户在面临长期存储或频繁查阅需求时面临挑战。


为应对这一问题,将网页内容转化为PDF文件不失为一种有效的解决方案。PDF格式具备跨操作系统、跨设备兼容性以及良好的防篡改特性,能确保网页内容的原始状态与完整性得到忠实保留。


通过将整个网页或特定区域转换为PDF,用户可以在任何环境下便捷地访问已保存的网页信息,无论是在离线状态下还是需要长期归档时,都能轻松查阅所需内容。这种转换方式不仅提升了个人用户的资料管理效率,也为学术研究者、数据分析员等专业人士提供了更高效、规范化的资料整理手段。


图 1-示例网页(Vue3+ElementPlus)



Part2

实现策略


实现网页到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的转换实现。



Part3

基础实现


对于结构简单的网页,直接借助浏览器内置功能或第三方库将整个页面转换为PDF通常可以满足需求。以下以示例网页为例,说明如何利用html2canvas(https://html2canvas.hertzen.com/)与jspdf(https://github.com/parallax/jsPDF)这两个库将其内容输出为PDF文件:


1. 获取待转换元素:首先通过document.getElementById获取待转换的DOM元素。


let element = document.getElementById("element-to-print");


2. 将元素转换为canvas:调用html2canvas函数,传入目标元素,并设置相关配置项(如允许跨域、画布X/Y坐标等),等待返回转换后的canvas对象。


let canvas = await html2Canvas(element, {
    allowTaint: true,
    scrollY: 0,
    scrollX: 0,
    useCORS: true
  });


图 3-html2canvas部分配置项


3. canvas转为图片数据:利用canvas的toDataURL方法将canvas内容转化为指定格式(如PNG)的图片数据。


let pageData = canvas.toDataURL("image/png");


4. 将图片数据写入PDF:初始化一个jsPDF实例,设定纸张大小为A4,并使用addImage方法将图片数据插入PDF文档。该方法接受图片数据、格式、坐标(x, y)、尺寸(width, height)以及可选的别名、压缩比和旋转角度等参数。


// 新建一个pdf
  let PDF = 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");



Part4

功能完善


在实际应用中,可能会遇到更复杂的需求和场景,例如:


● 自动分页:为了便于打印,需将PDF按照A4纸尺寸进行合理分页。那么在生成PDF的过程中,需监控图片数据的高度,当其接近或超过一页A4纸的高度时,触发addPage方法添加新页,继续在下一页放置后续图片。


● 元素高度超限处理:对于高度超过一页A4纸的网页元素,如长表格或大型图表,需采取特殊策略。对于可分割的元素(如表格,文章),可以按行或按一定高度阈值拆分为多个子部分,分别插入PDF;对于不可分割的元素,则考虑对其进行适当缩放或分页截取,确保内容能在多页中完整展现,同时保持较好的阅读体验。


// 核心步骤:将图片铺设到pdf页
const addImage = img => {
  let imgPageWidth = pdfPage.width; // 图片铺设到pdf页上面的宽度,设置为pdf页的可用宽度(即A4纸宽度-左右内边距)
  let imgPage = {
    width: imgPageWidth, // 图片铺设宽度
    height: (img.height / img.width) * imgPageWidth // 图片铺设高度=(图片本身高度/图片本身宽度)*图片铺设宽度
  };
  // 若图片铺设高度大于一页A4纸高度,则进行二次处理
  if (imgPage.height > pdfPage.height) {
    // 策略一:图片正常铺设,超出一页纸高度的部分则截断
    // pdfPostion:pdf插入内容的位置,初始值为A4纸的上内边距,每插入一张图片,则加上图片的高度
    let _pdfPostion = pdfPostion;
    // leftImgHeight:待插入图片的高度
    let remainingHeight = 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;
  }
};



Part5

效果演示


以下是当示例网页中表格超高时,对表格采取了分割处理,将表格按行分割成多张图片,生成的pdf:


图 4-超长表格第1页


图 5-超长表格第2页


以下是当网页中包含超长图片时,图片被截断,生成的pdf:


图 6-超长图片第1页


以下是当网页中包含超长图片时,图片被整体缩小,生成的pdf:


图 7-超长图片第2页



Part6

总结


综上所述,通过利用浏览器内置功能或集成第三方前端库,可有效地将网页内容以纯前端方式转换为PDF文件,满足用户对网页内容长期保存、离线查阅的需求。针对各类复杂场景,则需要选择适当的处理策略,确保生成的PDF文档既符合预期的格式标准,又能再现原始网页信息。





Hello~

这里是神州数码云基地
编程大法,技术前沿,尽在其中
超多原创技术干货持续输出ing~


想要第一时间获取
超硬技术干货
快快点击关注+设为星标



- END -


往期精选




手把手教你打造前端规范工程




你不知道的ES6新特性Reflect最全使用方法总结




一文搞懂利用plop生成项目模板文件


了解云基地,就现在!

【声明】内容源于网络
0
0
AI实践工程院
我们致力于用数字技术重构企业价值,助力企业实现数字化转型升级。
内容 434
粉丝 0
AI实践工程院 我们致力于用数字技术重构企业价值,助力企业实现数字化转型升级。
总阅读429
粉丝0
内容434