页面转 PDF 功能的实现思路与使用方法
引言
在 Web 开发中,有时我们需要将页面的特定部分转换为 PDF 格式,以便用户下载和保存。本文将详细介绍如何使用 html2canvas 和 jspdf 这两个强大的库来实现这一功能,并且结合实际代码讲解其实现思路与使用方法。完整源码(src/utils/htmlToPdf.js):https://gitcode.com/Jiaberrr/vue3-pc-template/overview
一、前置准备
首先,确保你的项目中已经安装了 html2canvas 和 jspdf 库,以及 element-plus(用于展示加载状态)。在代码中引入相关依赖:
import html2canvas from 'html2canvas'; // 将 html 页面转换成图片import jsPDF from 'jspdf'; // 将图片生成 pdfimport { ElLoading } from 'element-plus';
二、代码实现思路
(一)核心函数 downloadPdf
我们封装了一个名为 downloadPdf 的异步函数,它接收两个参数:elementId 和 pdfName。
export async function downloadPdf(elementId, pdfName) {//...}
- elementId:用于指定页面中要转换为 PDF 的元素(盒子)的 ID,该盒子内部包含了我们想要生成 PDF 的内容。
- pdfName:生成的 PDF 文件的名称。
(二)加载状态展示
在函数内部,首先使用 ElLoading 组件来显示一个加载提示,让用户知道正在进行下载操作。
const loadingInstance = ElLoading.service({lock: true,text: '下载中',spinner: 'el-icon-loading',background: 'rgba(0, 0, 0, 0.8)'});
(三)页面样式调整
获取要转换的 DOM 元素,并将其背景设置为白色,同时调整宽度为 190mm,以适配后续的 A4 纸布局。这里还保存了原始的样式,以便在转换完成后恢复。
let pdfDom = document.getElementById(elementId);pdfDom.style.background = '#FFFFFF';const originalStyle = pdfDom.getAttribute('style');pdfDom.style.width = '190mm';
(四)延迟执行与页面截图
设置一个短暂的延迟(100 毫秒)后执行 htmlToCanvas 函数,开始对指定元素进行截图操作。这是因为页面样式调整可能需要一点时间生效,确保截图的准确性。
setTimeout(() => {htmlToCanvas(pdfDom);}, 100);
(五)图片转 PDF 核心逻辑
- htmlToCanvas 函数:使用 html2canvas 库对指定的 DOM 元素进行截图,它接收一些配置参数,如关闭日志输出(logging: false)和启用跨域资源加载(useCORS: true)。当截图成功后,获取到 canvas 对象,接着创建一个 jsPDF 实例,设置为纵向 A4 纸布局。
function htmlToCanvas(pdfDom) {html2canvas(pdfDom, {logging: false,useCORS: true}).then((canvas) => {// eslint-disable-next-line new-caplet pdf = new jsPDF('p', 'mm', 'a4');canvasToPdf(canvas, pdf);//...后续操作});}
- canvasToPdf 函数:这是将 canvas 图片转换为 PDF 内容的关键函数。首先获取 canvas 的 2D 绘图上下文,定义 A4 纸的尺寸(考虑四边 10mm 边距,显示区域为 190 x 277)。然后通过循环,按照 A4 纸的显示比例,将 canvas 中的内容逐页添加到 PDF 中。如果内容高度超过一页,会自动添加新的页面,确保所有内容都能完整转换。
function canvasToPdf(canvas, pdf) {let ctx = canvas.getContext('2d');let a4w = 190;let a4h = 277;let imgH = Math.floor(canvas.width / a4w * a4h);let renderH = 0;while (renderH < canvas.height) {let page = document.createElement('canvas');page.width = canvas.width;page.height = Math.min(imgH, canvas.height - renderH);page.getContext('2d').putImageData(ctx.getImageData(0, renderH, canvas.width, Math.min(imgH, canvas.height - renderH)), 0, 0);pdf.addImage(page.toDataURL('image/jpeg', 1.0), 'JPEG', 10, 10, a4w, Math.min(a4h, a4w * page.height / page.width));renderH += imgH;if (renderH < canvas.height) {pdf.addPage();}}}
(六)收尾操作
在 PDF 生成并保存后,关闭加载提示,同时将之前转换的 DOM 元素的样式恢复为原始状态。
loadingInstance.close();pdf.save(pdfName + '.pdf');if (originalStyle) {pdfDom.setAttribute('style', originalStyle);}
三、使用方法
在你的项目中,当需要将某个页面区域转换为 PDF 时,只需按照以下方式调用 downloadPdf 函数:
// 假设页面中有一个 ID 为'myContent' 的 div 元素,要将其内容转换为 PDF 并命名为'myDocument'downloadPdf('myContent','myDocument');
通过以上步骤,就可以轻松实现页面转 PDF 的功能,为用户提供便捷的文档下载体验。希望本文对你理解和使用该功能有所帮助,如有任何疑问,欢迎在评论区交流。
相关文章:
页面转 PDF 功能的实现思路与使用方法
引言 在 Web 开发中,有时我们需要将页面的特定部分转换为 PDF 格式,以便用户下载和保存。本文将详细介绍如何使用 html2canvas 和 jspdf 这两个强大的库来实现这一功能,并且结合实际代码讲解其实现思路与使用方法。完整源码(src/…...
【保姆级教程】基于OpenCV+Python的人脸识别上课签到系统
【保姆级教程】基于OpenCVPython的人脸识别上课签到系统 一、软件安装及环境配置1. 安装IDE:PyCharm2. 搭建Python的环境3. 新建项目、安装插件、库 二、源文件编写1. 采集人脸.py2. 训练模型.py3. 生成表格.py4. 识别签到.py5. 创建图形界面.py 三、相关函数分析1.…...
docker-compose部署下Fastapi中使用sqlalchemy和Alembic
本篇介绍使用Fastapi sqlalchemy alembic 来完成后端服务的数据库管理,并且通过docker-compose来部署后端服务和数据库Mysql。包括: 数据库创建,数据库用户创建数据库服务发现Fastapi 连接数据库Alembic 连接数据库服务健康检查 部署数据…...
Oracle:ORA-00904: “10“: 标识符无效报错详解
1.报错Oracle语句如下 SELECT YK_CKGY.ID,YK_CKGY.DJH,YK_CKGY.BLRQ,YK_CKGY.ZBRQ,YK_CKGY.SHRQ,YK_CKGY.YT,YK_CKGY.ZDR,YK_CKGY.SHR,YK_CKGY.BZ,YK_CKGY.JZRQ,YK_CKGY.ZT,YK_CKGY.CKLX,(case YK_CKGY.CKLXwhen 09 then药房调借when 02 then科室退药when 03 then损耗出库when…...
C语言#define定义宏
目录 一、什么是宏以及宏的声明方式 1.宏常量: 2.宏函数: 二、宏的替换原则 三、宏设计的易犯错误 ERROR1:尾部加分号(当然有些特定需要加了分号,这里说明一般情况) ERROR2:宏函数定义时&…...
SpringBoot操作spark处理hdfs文件
SpringBoot操作spark处理hdfs文件 1、导入依赖 <!-- spark依赖--><dependency><groupId>org.apache.spark</groupId><artifactId>spark-core_2.12</artifactId><version>3.2.2</version></dependency><depend…...
消息队列架构、选型、专有名词解释
私人博客传送门 消息队列专有名词解释 | 魔筝炼药师 MQ选型 | 魔筝炼药师 MQ架构 | 魔筝炼药师 MQ顺序消息 | 魔筝炼药师...
用OpenCV实现UVC视频分屏
分屏 OpencvUVC代码验证后话 用OpenCV实现UVC摄像头的视频分屏。 Opencv opencv里有很多视频图像的处理功能。 UVC Usb 视频类,免驱动的。视频流格式有MJPG和YUY2。MJPG是RGB三色通道的。要对三通道进行分屏显示。 代码 import cv2 import numpy as np video …...
Allure 集成 pytest
Allure 是一个强大的测试报告工具,与 pytest 集成可以生成详细的测试报告,包括测试步骤、测试数据、截图、错误堆栈等。 1. 安装 Allure 和相关依赖 安装 pytest-allure-adaptor 插件: pip install allure-pytest确保本地已安装 Allure 工具。…...
【Python】构建智能语音助手:使用Python实现语音识别与合成的全面指南
随着人工智能技术的迅猛发展,语音助手已成为人们日常生活中不可或缺的一部分。从智能手机到智能家居设备,语音交互提供了便捷高效的人机交互方式。本文旨在全面介绍如何利用Python编程语言及其强大的库——SpeechRecognition和gTTS,构建一个基…...
在 Arthas 中调用 Spring Bean 方法
获取 Spring 应用上下文 使用工具类 如果你的项目中有一个工具类实现了 ApplicationContextAware 接口,如 cn.shutdown.pf.utils.SpringContextUtils,可以使用该类获取 ApplicationContext: Component public final class SpringContextUt…...
Nginx入门笔记
Nginx入门笔记 一、Nginx基本概念二、代理1、正向代理2、反向代理 三、准备工作1、CentOS 7安装nginx(1). 安装必要的依赖(2)下载nginx(3)编译安装(4)编译并安装 Nginx(5)启动nginx …...
【单片机】实现一个简单的ADC滤波器
实现一个 ADC的滤波器,PT1 滤波器(也称为一阶低通滤波器),用于对输入信号进行滤波处理。 typedef struct PT1FilterSettings PT1FilterSettings; struct PT1FilterSettings {//! last Filter output valueuint32_t filtValOld;//…...
开源 vGPU 方案 HAMi 解析
开源 vGPU 方案 HAMi 一、k8s 环境下 GPU 资源管理的现状与问题 (一)资源感知与绑定 在 k8s 中,资源与节点紧密绑定。对于 GPU 资源,我们依赖 NVIDIA 提供的 device-plugin 来进行感知,并将其上报到 kube-apiserver…...
备考蓝桥杯:顺序表详解(静态顺序表,vector用法)
目录 1.顺序表的概念 2.静态顺序表的实现 总代码 3.stl库动态顺序表vector 测试代码 1.顺序表的概念 要理解顺序表,我们要先了解一下什么是线性表 线性表是n个具有相同特征的数据元素的序列 这就是一个线性表 a1是表头 a4是表尾 a2是a3的前驱 a3是a2的后继 空…...
OA系统如何做好DDOS防护
OA系统如何做好DDOS防护?在数字化办公蔚然成风的当下,OA(办公自动化)系统作为企业内部管理与协作的神经中枢,其安全性和稳定性直接关系到企业的日常运营效率、信息流通效率以及长远发展。OA系统不仅承载着企业内部的日…...
使用 Python 的 pyttsx3 库进行文本转语音
1. 什么是 pyttsx3? 1.1 pyttsx3 是一个 Python 库,它可以将文本转换为语音。与其他文本转语音库(如 gTTS)不同,pyttsx3 不依赖于网络服务,它使用本地的 TTS(Text-to-Speech)引擎&a…...
如何在Windows上编译OpenCV4.7.0
前言 参考:Win10 下编译 OpenCV 4.7.0详细全过程,包含xfeatures2d 这里在其基础上还出现了一些问题,仅供参考。 正文 一、环境 1、win10 2、cmake-gui 3、opencv4.7.0 4、VS2019 二、编译过程 1、下载需要的文件: 通…...
【玩转全栈】----Django连接MySQL
阅前先赞,养好习惯! 目录 1、ORM框架介绍 选择建议 2、安装mysqlclient 3、创建数据库 4、修改settings,连接数据库 5、对数据库进行操作 创建表 删除表 添加数据 删除数据 修改(更新)数据: 获取数据 1、OR…...
25/1/4 算法笔记<强化学习> 生成对抗模仿学习
基于生成对抗网络的模仿学习,假设存在一个专家智能体,其策略可以看成最优策略,我们就可以通过直接模仿这个专家在环境中交互的动作数据来训练一个策略,并不需要用到环境提供的奖励信息。 生成对抗模仿学习GAIL实质上就是模仿了专家…...
实时行情系统设计:从协议选择到高可用架构,再到数据源选型蘸
一、核心问题及解决方案(按踩坑频率排序) 问题 1:误删他人持有锁——最基础也最易犯的漏洞 成因:释放锁时未做身份校验,直接执行 DEL 命令删除键。典型场景:服务 A 持有锁后,业务逻辑耗时超过锁…...
IOFILE结构体的介绍与House of orange媚
认识Pass层级结构 Pass范围从上到下一共分为5个层级: 模块层级:单个.ll或.bc文件 调用图层级:函数调用的关系。 函数层级:单个函数。 基本块层级:单个代码块。例如C语言中{}括起来的最小代码。 指令层级:单…...
PostgreSQL 数据误删 止损操作
一、核心原理:为什么数据能恢复? 在 PostgreSQL 中,执行 DELETE 操作后,数据并不会立即从磁盘上物理擦除。PostgreSQL 使用多版本并发控制(MVCC)机制,删除操作仅仅是给数据行打上了一个“已删…...
黑马点评实战篇知识点整理-秒杀进阶
异步秒杀思路问题:串行执行,性能不行(查询库存,查询订单,扣减库存,写入订单,全是数据库,还加了锁,性能不行)把判断秒杀资格和一人一单放到redis里保存用户id&…...
如何3分钟告别GitHub英文界面困扰?中文翻译插件全攻略
如何3分钟告别GitHub英文界面困扰?中文翻译插件全攻略 【免费下载链接】github-chinese GitHub 汉化插件,GitHub 中文化界面。 (GitHub Translation To Chinese) 项目地址: https://gitcode.com/gh_mirrors/gi/github-chinese 你是否曾在GitHub上…...
3步掌握抖音无水印下载:让视频采集效率提升300%
3步掌握抖音无水印下载:让视频采集效率提升300% 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback support. 抖…...
UE5.4渲染设置详解:从‘眼部适应’到‘后处理Volume’,一步步驯服自动曝光
UE5.4曝光控制全链路解析:从视觉原理到多层级精准调控 当你在昏暗的UE5场景中点燃一盏虚拟烛光时,引擎如何决定该让画面保持幽暗氛围还是强行提亮所有细节?这背后是一场由眼部适应算法主导的"亮度战争"。不同于简单开关的二元选择&…...
ArcGIS Pro实战:5分钟搞定气象站点TXT坐标转面状Shapefile(附Python脚本)
ArcGIS Pro气象数据处理实战:从TXT坐标到面状Shapefile的高效转换 在地理信息系统(GIS)工作中,气象站点数据的处理是常见但容易出错的环节。许多气象数据以TXT格式存储,包含站点坐标和边界信息,而将这些数据转换为GIS可用的面状Sh…...
U-Boot调试必备:md命令验证SPI Flash的原理与实操细节
要搞懂md命令为何能验证SPI Flash,核心是理清两个关键: md命令的本质功能; SPI Flash的存储映射访问模式。 这两者的结合,才让“用md命令验证Flash”成为可能,而且这也是嵌入式开发中最常用、最便捷的Flash验证方式之一。 ddr与spi控制器一种连接方式 先明确md命令的核…...
5个核心概念理解上下文工程:从Prompt Engineering到Context Engineering的范式转移
5个核心概念理解上下文工程:从Prompt Engineering到Context Engineering的范式转移 【免费下载链接】Awesome-Context-Engineering 🔥 Comprehensive survey on Context Engineering: from prompt engineering to production-grade AI systems. hundred…...
