前端生成pdf之html2canvas+jsPDF,以及解决图片不显示bug
前端如何生成pdf
开发背景: 需要给页面中相应的内容生成pdf,查找文档后发现要用到两个插件。html2canvas 以及 jsPDF
html2canvas
给dom结构转化为canvas,然后生成各种类型图片jsPDF
把canvas 生成的图片url 转化为pdf
// 插入图片
pdf.addImage(image, format, x, y, width, height, alias, compression, rotation)
// 保存为pdf
pdf.save("example.pdf");
参数
- image:表示要插入的图片资源,可以是图片文件的路径或者base64编码字符串。
- format:表示要插入的图片格式,包括:‘JPEG’, ‘PNG’, ‘GIF’, ‘BMP’, ‘TIFF’, ‘RAW’, ‘JPEG2000’。
- x:图片在PDF中的x轴坐标,单位为pt(点)。
- y:图片在PDF中的y轴坐标,单位为pt(点)。
- width:图片在PDF中的宽度,单位为pt(点)。
- height:图片在PDF中的高度,单位为pt(点)。
- alias(可选):指定图片资源的别名。
- compression(可选):指定图片的压缩质量,取值为0-1之间的浮点数。
- rotation(可选):指定图片的旋转角度,取值范围为0-360之间的整数。
下面是dom转化为pdf 的基本代码
import html2canvas from 'html2canvas';
import jsPdf from 'jspdf';function printPDF () {const domElement = document.getElementById('your-id');html2canvas(domElement, {onclone: (document) => {document.getElementById('print-button').style.visibility = 'hidden';}}).then((canvas) => {const img = canvas.toDataURL('image/png');const pdf = new jsPdf();pdf.addImage(imgData, 'JPEG', 0, 0, width, height);pdf.save('your-filename.pdf');
})
需要特别注意一下 html2canvas onclone
方法。它是当DOM被克隆后进行渲染时的回调函数,可用于修改将要渲染的内容,而不会影响原始DOM。当你需要在生成快照前操作 DOM(例如隐藏打印按钮)时,会非常有用。
难点突破
1. 使用html2canvas转为图片遇到跨域问题
跨域图片不会生成:由于跨域的问题(比如图片在第三方存放),导致图片不会被绘制,需要多方配置;
1. html2canvas
的配置项中配置 allowTaint:true
或 useCORS:true
(二者不可共同使用)
2. img标签增加 crossOrigin='anonymous'
3. 图片服务器配置Access-Control-Allow-Origin
或使用代理
其中第三步是最重要的,不设置则前两步设置了也无效。
如果后端不能改图片服务器,咱们前端也能设置图片代理,例如nginx server配置
location /img {proxy_pass 服务器真正地址;}
2. html2canvas转化的图片,ios设备长按可以保存,Android设备长按无法保存
- 原因分析:转换后使用canvas.toDataURL拿到的是base64的图片,此图片可以直接展示在网页上,但是在Android设备上长按此图片无法保存,ios设备可以长按保存;原因是Android无法长按保存base64的图片,
- 解决办法:可以考虑将图片先上传到服务器拿到url再展示
3. safir长按保存不了图片
使用-webkit-touch-callout:default
不规范的属性,iOS 2.0及更高版本的Safari浏览器可用
4. 生成的图片中若包含二维码,微信长按图片偶现无法识别
不使用路由切换,使用window.location.href直接跳转刷新页面
5. 生成的PDF超出一页后分页问题
- 需要计算图片的宽高,一页展示多少
看详细代码
printPDF(id, name){const domElement = document.getElementById(id);html2canvas(domElement, {allowTaint: false,useCORS: true, // 用于解决图片跨域onclone: (document) => {document.getElementById('print-button').style.visibility = 'hidden';}}).then((canvas) => {const fileName = name + (new Date()).toLocaleString() + '.pdf'var pdf = new jsPdf('p', 'mm', 'a4'); // A4纸,纵向var ctx = canvas.getContext('2d');var a4w = 190; var a4h = 277; // A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277var imgHeight = Math.floor(a4h * canvas.width / a4w); // 按A4显示比例换算一页图像的像素高度var renderedHeight = 0;while (renderedHeight < canvas.height) {var page = document.createElement('canvas');page.width = canvas.width;page.height = Math.min(imgHeight, canvas.height - renderedHeight);// 可能内容不足一页 // 用getImageData剪裁指定区域,并画到前面创建的canvas对象中page.getContext('2d').putImageData(ctx.getImageData(0, renderedHeight, canvas.width, Math.min(imgHeight, canvas.height - renderedHeight)), 0, 0);pdf.addImage(page.toDataURL('image/jpeg', 1.0), 'JPEG', 10, 10, a4w, Math.min(a4h, a4w * page.height / page.width)); // 添加图像到页面,保留10mm边距renderedHeight += imgHeight;if (renderedHeight < canvas.height) {pdf.addPage();// 如果后面还有内容,添加一个空页}// delete page;}// 保存文件pdf.save(fileName);})}
相关文章:
前端生成pdf之html2canvas+jsPDF,以及解决图片不显示bug
前端如何生成pdf 开发背景: 需要给页面中相应的内容生成pdf,查找文档后发现要用到两个插件。html2canvas 以及 jsPDF html2canvas 给dom结构转化为canvas,然后生成各种类型图片jsPDF 把canvas 生成的图片url 转化为pdf // 插入图片 pdf.addI…...
PHP常用符号和函数
// 单行注解 /* */ 多行注解 引号的使用 ’ ’ 单引号,没有任何意义,不经任何处理直接拿过来; ” “双引号,php动态处理然后输出,一般用于变量. 变量形态: 一种是True 即 真的; 另一种是False 即假的 常见变量形态: string 字串(数字\汉字\等等) integer 整数(1、2、…...

C#,入门教程(12)——数组及数组使用的基础知识
上一篇: C#,入门教程(11)——枚举(Enum)的基础知识和高级应用https://blog.csdn.net/beijinghorn/article/details/123917587 数组是一种数据集合,是一组完全相同的、按顺序存放的数据。 需要记住数组的几个特征&…...
C语言中的副作用、序列点以及复杂表达式的求值顺序
C语言中复杂表达式的求值顺序 num (5 2) * (9 * 6);如果我问你:上面的c程序在执行的时候到底是先算(5 2)还是(9 * 6)?你会怎么回答? 无非就两种:先算(5 2ÿ…...

C++学习笔记——队列模拟
目录 一、模拟队列 二、模拟队列的知识点 三、队列 3.1入队操作 3.2出队操作 3.3访问队首元素 3.4访问队尾元素 3.5判断队列是否为空 3.6获取队列的大小 四、实现队列的基本功能 一、模拟队列 当涉及到数据存储和处理时,队列是一种常见的数据结构&#x…...
jvm垃圾回收相关的算法
什么是垃圾 JVM主要通过以下几种方式来判断对象是否需要回收: 引用计数法:JVM通过引用计数器来判断对象的引用数量,当引用数量为0时,表示对象可以被回收。 可达性分析算法:JVM通过根对象(如栈中的引用、静…...
每日coding
2085、统计出现过一次的公共字符串 给你两个字符串数组 words1 和 words2 ,请你返回在两个字符串数组中 都恰好出现一次 的字符串的数目。 示例 1: 输入:words1 ["leetcode","is","amazing","as"…...
软件工程_复习
软件工程 软件危机(1968 60年代) 产生软件危机的原因: 一方面与软件本身的特点有关,另一方面也和软件开发和维护的方法不正确有关。 与软件本身特点有关: 1.软件不同于硬件,软件是计算机系统中的逻辑部件,缺乏“可见性”,管理和控制软件开发过程相当困难 2.软件在运行过…...
07GoF之三种工厂模式
GoF(Gang of Four):四人组,《Design Patterns: Elements of Reusable Object-Oriented Software》(《设计模式》)的作者,设计了23种设计模式.但时代发展,还有其它的设计模式,比如:JavaEE的设计模式(DAO模式…...
JAVA面试部分——后端-线程前篇
3.1 线程和进程 在计算机科学中,进程和线程是操作系统管理资源的两种不同方式。 进程(Process):是程序在计算机上的一次执行活动。每个进程都有自己的内存空间,包括代码、数据和系统资源。一个进程可以包含多个线程。…...

【小沐学C++】C++ 实现鼠标键盘钩子HOOK
文章目录 1、简介2、相关函数2.1 SetWindowsHookEx2.2 UnhookWindowsHookEx2.3 CallNextHookEx 3、相关结构体3.1 KBDLLHOOKSTRUCT3.2 MSLLHOOKSTRUCT 4、挂钩过程5、代码测试5.1 代码1 结语 1、简介 https://learn.microsoft.com/zh-cn/windows/win32/winmsg/about-hooks 挂…...
【pycharm】常见问题与解决
记录一些Pycharm中经常遇到的问题 1. “Open file or Project” always in loading state (hang) a) 老版本 (2021年左右) since build 211.6693.14, it is possible to use a native file chooser on Windows. The feature is experimental; to enable it, add the followi…...
flask web学习之表单(一)
文章目录 一、使用Flask-WTF处理表单1.1 安装Flask-WTF库1.2 定义WTForms表单类常用的WTForm字段实例化字段类常用参数常用的WTForm验证器 1.3 输出HTML代码使用render_kw属性在调用字段时传入 1.4 在模板中渲染表单 在web程序中,表单是用户交互最常见的方式之一。用…...

@ControllerAdvice 使用场景
ControllerAdvice 是Spring 框架中的注解,多用在Spring MVC应用程序中。 使用场景1:处理异常 # 示例1 import org.apache.ibatis.javassist.NotFoundException; import org.springframework.http.HttpStatus; import org.springframework.http.Respons…...

二极管选型怎么选?常用参数要熟练~
同学们大家好,今天我们继续学习杨欣的《电子设计从零开始》,这本书从基本原理出发,知识点遍及无线电通讯、仪器设计、三极管电路、集成电路、传感器、数字电路基础、单片机及应用实例,可以说是全面系统地介绍了电子设计所需的知识…...

【小白专用】C#关于角色权限系统
(C#)用户、角色、权限 https://www.cnblogs.com/huangwen/articles/638050.html 权限管理系统——数据库的设计(一) https://www.cnblogs.com/cmsdn/p/3371576.html 权限管理系统——菜单模块的实现(二) …...
代码随想录算法训练营
一刷打卡记录: 日期打卡2023/10/25 day01二分查找有点转不过弯,快慢指针能理解,自己写也可能写不出来,但是能记住了,能看懂,还有其他解法待补充看完,花了挺长时间的2023/10/26 day02还好&#…...

统计学-R语言-3
文章目录 前言给直方图增加正态曲线的不恰当之处直方图与条形图的区别核密度图时间序列图洛伦茨曲线计算绘制洛伦茨曲线所需的各百分比数值绘制洛伦茨曲线 练习 前言 本篇文章是介绍对数据的部分图形可视化的图型展现。 给直方图增加正态曲线的不恰当之处 需要注意的是&#…...
spring动态控制定时任务
在spring框架中,对于简单的定时任务,可以使用 Scheduled 注解实现,在实际项目中,经常需要动态的控制定时任务,比如通过接口增加、启动、停止、删除定时任务,动态的改变定时任务的执行时间等。 我们可以通过…...
3. Mybatis 中SQL 执行原理
2. Mybatis 中SQL 执行原理 这里有两种方式,一种为常用的 Spring 依赖注入 Mapper 的方式。另一种为直接使用 SqlSessionTemplate 执行 Sql 的方式。 Spring 依赖注入 Mapper 的方式 Mapper 接口注入 SpringIOC 容器 Spring 容器在扫描 BeanDefinition 阶段会扫…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...
Java数值运算常见陷阱与规避方法
整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

uniapp 小程序 学习(一)
利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 :开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置,将微信开发者工具放入到Hbuilder中, 打开后出现 如下 bug 解…...
小木的算法日记-多叉树的递归/层序遍历
🌲 从二叉树到森林:一文彻底搞懂多叉树遍历的艺术 🚀 引言 你好,未来的算法大神! 在数据结构的世界里,“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的,它…...