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

news2024/12/24 8:24:46

目录

一、需求背景

二、实现策略

三、基础实现

四、功能完善

五、效果演示

六、总结


一、需求背景

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

为应对这一问题,将网页内容转化为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文档既符合预期的格式标准,又能再现原始网页信息。

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

版权声明:本文由神州数码云基地团队整理撰写,若转载请注明出处。

公众号搜索神州数码云基地,了解更多技术干货。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1821701.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

郑州企业资信评价资质:工程咨询单位专业资信申报材料清单

在郑州企业申请工程咨询单位专业资信评价资质时,需要准备一系列详细的申报材料。以下是根据参考文章中的相关数字和信息,清晰、分点表示和归纳的工程咨询单位专业资信申报材料清单: 一、基础材料 企业法人营业执照:提供企业法人营…

微信小程序投票系统(包含微信小程序端)

📱微信投票小程序:轻松发起,快速统计 一、引言 在数字化时代,微信作为我们日常生活中不可或缺的社交工具,不仅为我们提供了沟通交流的平台,还衍生出了许多实用的小程序。其中,微信投票小程序凭…

《现代通信原理与技术》--数字信号的最佳接收实验报告

《现代通信原理与技术》 数字信号的最佳接收实验报告 实 验:数字信号的最佳接收实验报告 目录 摘要......................................................................................................3 引言........................................…

嵌入式系统复习(一)

第一章 嵌入式系统的定义、特点 嵌入式系统是以应用为中心,以计算机技术为基础,软件硬件可裁剪,适应应用系统对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。 特点:嵌入性 专用性 计算机系统 嵌入式系统典型组成…

线代老师大PK,这四位胜出!

说实话,线代真的别乱跟老师 因为每个老师讲课适用的人群不一样,比如都说李永乐老师线代讲的好,但是我去听完发现,李永乐老师的线代讲的虽然好,但是对于零基础或者基础不好的考生来说,真的有点不友好&#…

Python开发者必备:Python多平台消息推送工具

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 文章内容 📒🚀 安装📝 使用方法📝 同步发送消息📝 异步发送消息📝 使用配置文件发送消息📝 示例配置文件⚓️ 相关链接 ⚓️📖 介绍 📖 你是否需要一个强大且灵活的工具来实现多平台消息推送?那么你一定不能…

手机直播不用麦克风可以吗?一文看懂无线麦克风哪个好

市面上对于无线麦克风的需求有增无减,原因是直播、短视频行业火爆,许多人都开始加入这一行业,不过对于麦克风这类产品的疑问也越来越多。例如:无线麦克风怎么选?实不实用?手机直播不用麦克风可以吗&#xf…

服务器数据恢复—EMC Isilon存储中被误删的虚拟机数据恢复案例

服务器存储数据恢复环境: EMC Isilon S200集群存储,共三个节点,每节点配置12块SATA硬盘。 服务器存储故障: 工作人员误操作删除虚拟机,虚拟机中数据包括数据库、MP4、AS、TS类型的视频文件等。需要恢复数据的虚拟机通…

雪球产品学习,大雪球vs小雪球

part1 大雪球 一、 雪球产品的要素 1.1 定义:固收+期权的结合 具备敲入,敲出的Barrier put (看跌=认沽) 期权的买方:产品发行方 期权的卖方:雪球产品购买者 1.2 七要素 挂钩标的,锁定期,敲入价格,敲出价格,产品期限,观察频率,产品报价 1.3 挂钩标的 个股or指…

AI类人工智能产品经理的丛林法则

AI是大家都很关注的领域,然而对于大部分想要入行的同学来讲,AI的算法技术门槛相对较高,让很多空有热血但是缺少数学背景的同学望而却步。不知道什么时候,可能是“人人都是产品经理”这个论调的影响,产品经理这个岗位逐…

剖析框架代码结构的系统方法(下)

当面对Dubbo、Spring Cloud、Mybatis等开源框架时,我们可以采用一定的系统性的方法来快速把握它们的代码结构。这些系统方法包括对架构演进过程、核心执行流程、基础架构组成和可扩展性设计等维度的讨论。 在上一讲中,我们已经讨论了架构演进过程和核心执行流程这两个系统方法…

【实践功能记录6】表格列悬浮展示tooltip信息

需求描述&#xff1a; 鼠标悬浮在表格的IP字段上时&#xff0c;使用tooltip展示IP信息&#xff0c;如图&#xff1a; 1.封装根据IP展示信息的组件 请求接口获取IP信息&#xff0c;注意请求接口时防抖 <!-- 根据IP展示资产信息 --> <template><div><el-…

vue-i18n使用步骤详解(含完整操作步骤)

开篇 下面是从创建vue项目开始&#xff0c;完整使用i18n实现国际化功能的步骤&#xff0c;希望对您有所帮助。 完整步骤 创建项目 创建项目&#xff0c;并在创建项目的时候选择vuex,router 选择3.x版本 后面随意选即可&#xff0c;下面是完整的代码结构 安装vue-i18n,并封装…

队列——Acwing.829模拟队列

队列 定义 队列是一种特殊的线性表&#xff0c;遵循先进先出&#xff08;First In First Out&#xff0c;FIFO&#xff09;的原则。可以进行入队&#xff08;在队尾添加元素&#xff09;和出队&#xff08;从队首移除元素&#xff09;操作。 运用情况 任务调度&#xff1a;…

vue3和ant-design 实现前端多种验证密码规则,最全的前端验证密码规则

1、小眼睛可以显示/隐藏明文密码&#xff08;无法用input typepassword&#xff0c;用css样式实现切换明文&#xff09; 2、输入长度统计&#xff08;不是自带的&#xff0c;用div写的&#xff0c;然后定位到框内的&#xff09; 3、每输入一个字符分别验证每一项规则&#xf…

C++ 34 之 单例模式

#include <iostream> #include <string.h> using namespace std;class King{// 公共的函数&#xff0c;为了让外部可以获取唯一的实例 public:// getInstance 获取单例 约定俗成static King* getInstance(){return true_king;}private: // 私有化// 构造函数设置为…

易趋(EasyTrack)资深咨询顾问刘苗受邀为第十三届中国PMO大会演讲嘉宾

全国PMO专业人士年度盛会 易趋&#xff08;EasyTrack&#xff09;资深咨询顾问刘苗女士受邀为PMO评论主办的2024第十三届中国PMO大会演讲嘉宾&#xff0c;演讲议题为“企业级项目管理平台推动 IPD 数字化”。大会将于6月29-30日在北京举办&#xff0c;敬请关注&#xff01; 议…

【Nginx系列】分发算法

文章目录 一、分发算法介绍二、nginx集群默认算法三、nginx业务服务器状态四、nginx集群默认算法测试实验环境实验拓扑4.1、轮询算法4.2、基于权重4.3、基于ip_hash分发4.4、基于url的hash &#x1f308;你好呀&#xff01;我是 山顶风景独好 &#x1f388;欢迎踏入我的博客世界…

STM32 Customer BootLoader 刷新项目 (一) STM32CubeMX UART串口通信工程搭建

STM32 Customer BootLoader 刷新项目 (一) STM32CubeMX UART串口通信工程搭建 文章目录 STM32 Customer BootLoader 刷新项目 (一) STM32CubeMX UART串口通信工程搭建功能与作用典型工作流程 1. 硬件原理图介绍2. STM32 CubeMX工程搭建2.1 创建工程2.2 系统配置2.3 USART串口配…

Centos系统yum安装mysql数据库

安装之前需要将系统自带的mariadb-libs软件包删除。 检查是否存在mariadb-libs包。 yum list installed|grep mariadb-libs 删除mariadb-libs包 yum -y remove mariadb-libs 声明&#xff1a; 系统&#xff1a;CentOS-7-x86_64-DVD-2009 安装为最小化安装&#xff0c;没…