使用html-to-image代替html2canvas,结合jspdf实现下载pdf(下载截图下载前端dom元素)
一、问题
一开始的时候,准备使用html2canvas+jspdf来实现的,但是遇到了一个麻烦的问题,在其他项目中使用html2canvas没有任何问题,但是在要开发的项目中使用,就给我报错,是真滴烦。
html2canvas报错

Uncaught (in promise) unable to find element in cloned iframe.
在github也看了很多,但是也没找到最终的解决办法。
html2canvas

这个错弄的人都炸裂了,当然html2canvas+jspdf的方法我还是想分享一下,当然这套代码是可以用的(但是在你的项目不一定能用):

npm i html2canvas jspdf
html2pdf.js
import html2Canvas from 'html2canvas';
import JsPDF from 'jspdf';
/*** [获取页面导出的pdf文件]* @param {[Object]} options [导出pdf配置项,包括一个title属性设置文件名,以及query属性设置获取元素的条件]*/
function getPdf(options) {var title = options.title || '标题';// 导出文件名,默认为“标题”const children = document.getElementsByClassName(options.className || 'pdf-content');let canvas = [];let i = 0;function toCanvas() {// if (children.length > 1) {html2Canvas(children[i], {dpi: 500, // 导出pdf清晰度background: '#fff', // 背景设为白色(默认为黑色)scale: 2,logging: false,useCORS: true,}).then(res => { // 计算每个dom的高度,方便后面计算分页res.imgWidth = 592.28;res.imgHeight = 592.28 / res.width * res.height;canvas.push(res);i++;if (canvas.length === children.length) {paging();toPdf();} else {toCanvas();}});// }}/*** [根据dom的高度初步进行分页,会将canvas组装为一个二维数组]*/function paging() {const imgArr = [[]];let pageH = 0; // 页面的高度let allH = 0; // 当前组所有dom的高度和let j = 0;for (let k = 0; k < canvas.length; k++) { // 涉及到k--的操作,使用for循环方便pageH += canvas[k].imgHeight;if (pageH > 841.89 && canvas[k].imgHeight < 841.89) { // 当某个页面装不下下一个dom时,则分页imgArr[j][0].allH = allH - canvas[k].imgHeight;allH = pageH = 0;k--;j++;imgArr.push([]);} else {if (canvas[k].imgHeight > 841.89) { // 特殊情况:某个dom高度大于了页面高度,特殊处理canvas[k].topH = 841.89 - (pageH - canvas[k].imgHeight); // 该dom顶部距离页面上方的距离pageH = (2 * canvas[k].imgHeight - pageH) % 841.89;canvas[k].pageH = pageH; // 该dom底部距离页面上方的距离}imgArr[j].push(canvas[k]);allH += canvas[k].imgHeight;}if (k === canvas.length - 1) imgArr[j][0].allH = allH;}canvas = imgArr;}/*** [生成PDF文件]*/function toPdf() {const PDF = new JsPDF('', 'pt', 'a4');canvas.forEach((page, index) => {let allH = page[0].allH;let position = 0;// pdf页面偏移if (index !== 0 && allH <= 841.89) PDF.addPage();page.forEach(img => {if (img.imgHeight < 841.89) { // 当某个dom高度小于页面宽度,直接添加图片PDF.addImage(img.toDataURL('image/jpeg', 1.0), 'JPEG', 0, position, img.imgWidth, img.imgHeight);position += img.imgHeight;allH -= img.imgHeight;} else { // 当某个dom高度大于页面宽度,则需另行处理while (allH > 0) {PDF.addImage(img.toDataURL('image/jpeg', 1.0), 'JPEG', 0, position, img.imgWidth, img.imgHeight);allH -= img.topH || 841.89;position -= img.topH || 841.89;img.topH = 0;if (allH > 0) PDF.addPage();}position = img.pageH;}});});PDF.save(title + '.pdf');}toCanvas();
}export default getPdf;
使用:
import getPdf from './html2pdf'getPdf({ className: "dom的类名", title: "下载pdf的文件名" });
html-to-image
参考:html-to-image github
html2canvas报错,还找不到解决办法我也是难受的一批,于是找到了它的替代方案
这个替代方案主要用户将html元素转成各种图片类型,不过里面的方法确实很多。
html-to-image 是一个使用 HTML5 canvas 和 SVG 从 DOM 节点生成图像的工具。
npm install --save html-to-image
用法
/* ES6 */
import * as htmlToImage from 'html-to-image';
import { toPng, toSvg, toJpeg, toBlob, toCanvas, toPixelData } from 'html-to-image';/* ES5 */
var htmlToImage = require('html-to-image');
toJpeg
保存并下载压缩的 JPEG 图像:
htmlToImage.toJpeg(document.getElementById('my-node'), { quality: 0.95 }).then(function (dataUrl) {var link = document.createElement('a');link.download = 'my-image-name.jpeg';link.href = dataUrl;link.click();
});
toCanvas
htmlToImage.toCanvas(document.getElementById('my-node')).then(function (canvas) {document.body.appendChild(canvas);});
我们就是要使用toCanvas这个方法,将他转成canvas元素然后再结合jspdf进行下载pdf文件
自己使用:
npm i html-to-image jspdf
import { toPng, toJpeg, toBlob, toPixelData, toSvg, toCanvas } from 'html-to-image';
import jsPDF from 'jspdf';
toCanvas(dom节点).then(function (canvas) {// document.body.appendChild(canvas);var contentWidth = canvas.width;var contentHeight = canvas.height;//一页pdf显示html页面生成的canvas高度;var pageHeight = contentWidth / 592.28 * 841.89;//未生成pdf的html页面高度var leftHeight = contentHeight;//页面偏移var position = 0;//a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高var imgWidth = 595.28;var imgHeight = 592.28 / contentWidth * contentHeight;var pageData = canvas.toDataURL('image/jpeg', 1.0);var pdf = new jsPDF('', 'pt', 'a4');//有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)//当内容未超过pdf一页显示的范围,无需分页if (leftHeight < pageHeight) {console.log(imgWidth, imgHeight, 'imgWidth, imgHeight')pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight);} else {while (leftHeight > 0) {pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)leftHeight -= pageHeight;position -= 841.89;//避免添加空白页if (leftHeight > 0) {pdf.addPage();}}}pdf.save(`xxxxxx.pdf`);}).catch((err) => {console.log(err)message.warning("导出PDF失败")});
效果:

相关文章:
使用html-to-image代替html2canvas,结合jspdf实现下载pdf(下载截图下载前端dom元素)
一、问题 一开始的时候,准备使用html2canvasjspdf来实现的,但是遇到了一个麻烦的问题,在其他项目中使用html2canvas没有任何问题,但是在要开发的项目中使用,就给我报错,是真滴烦。 html2canvas报错 Uncau…...
云环境渗透测试的重要性
🌕写在前面 🎉欢迎关注🔎点赞👍收藏⭐️留言📝 ✉️今日分享: “在这个世上,除了极稀少的例外,我们其实只有两种选择:要么是孤独,要么就是庸俗。” 随着云计…...
ROS2 入门应用 请求和应答(Python)
ROS2 入门应用 请求和应答(Python)1. 创建功能包1. 创建功能包2. 创建源文件2.1. 服务端2.2. 客户端3. 添加依赖关系4. 添加入口点5. 编译和运行1. 创建功能包 1. 创建功能包 在《ROS2 入门应用 工作空间》中已创建和加载了ros2_ws工作空间 在《ROS2 入…...
是德Keysight E4991A/e4991B射频阻抗/材料分析仪
Keysight E4991A 射频阻抗/材料分析仪提供终极阻抗测量性能和强大的内置分析功能。它将为评估 3 GHz 范围内组件的组件和电路设计人员的研发提供创新。E4991A 使用 RF-IV 技术,而不是反射测量技术,可在宽阻抗范围内进行更精确的阻抗测量。基本阻抗精度为…...
这才是计算机科学_人工智能
人工智能一、前言二、ML2.1 分类2.1.1 决策树2.2.2 支持向量机2.2.3 人工神经网络三、计算机视觉3.1 Prewitt算子3.2 Viola-Jones 人脸检测算法3.3 卷积神经网络四、自然语言处理4.1 知识图谱4.2 语音识别一、前言 之前讲了计算机从发展到现在的过程,计算机很适合做…...
DFS深度优先搜索—Java版
递归三要素 递归的定义 递归的拆解 递归的出口 什么时候使用DFS? 深度回溯问题(DFS与回溯区别不大) 二叉树问题 组合、排列问题 找方案问题(解空间是一棵树或者图,需要自行构造图/树) 图的搜索问题…...
RAY - 小记
文章目录关于 RAYRAY 结构关于 RAY Ray is a unified framework for scaling AI and Python applications. Ray consists of a core distributed runtime and a toolkit of libraries (Ray AIR) for accelerating ML workloads. RAY 是一个简单、通用的分布式计算框架。 RAY 解…...
金三银四软件测试工程师面试题(含答案)
前言:此文专门记载本人平时面试以及收藏的面试题目,如果有错误之处请及时指正,谢谢! 1、python的数据类型有哪些 答:Python基本数据类型一般分为:数字、字符串、列表、元组、字典、集合这六种基本数据类…...
Python 连接数据源与邮件功能(九)
文章目录一、概述二、Python 连接数据源1)Python MySQL 基础操作1、部署MySQL2、MySQL Connector 库【1】安装 mysql-connector-python 库【2】连接 MySQL【3】增加数据【4】查询数据【5】更新数据【6】删除数据2、PyMySQL 库【1】安装 PyMySQL 库【2】连接 MySQL【…...
网站如何锁定用户,超级浏览器有办法解决吗?
随着全球开放,跨境电商人纷纷开启了2023年的搞钱之旅,很多期待着在新的一年大干一场。但前事不忘后事之师,2022年跨境生意全面沦陷,其实除了大环境的因素之外,还有一个很重要的原因是,各个平台都开始实行非…...
Ubuntu下使用Wine运行HBuilderX
安装完wine后,在HbuilderX的目录中打开终端,直接输入wine HBuilderX.exe命令,启动过程中会提示安装wine-mono组件,点击安装按钮下载安装该组件,该组件下载速度慢,需要等待特别长时间。 安装完毕后&…...
如何高效远程维护分布在海外的中大型智能设备?
一、行业需求 随着越来越多的企业进行全球化经营,设备制造商和系统集成商的设备分布到全球各地,数量多而且分散,传统的设备运维方式,面临着出差成本高,工作效率低,服务不及时等问题,客户常常因…...
【双指针问题】LeetCode 925. 长按键入
Halo,这里是Ppeua。平时主要更新C语言,C,数据结构算法......感兴趣就关注我吧!你定不会失望。 🌈个人主页:主页链接 🌈算法专栏:专栏链接 我会一直往里填充内容哒! &…...
APP测试中IOS和Android的区别,有哪些注意点?
01、常识性区别 02、导航方式 iOS:Tab放在页面底部,不能通过滑动来切换,只能点击。也有放在上面的,也不能滑动,但有些Tab本身可以滑动,比如天猫的。还有新闻类的应用。 Android:一般放在页面…...
2019蓝桥杯真题平方序列(填空题) C语言/C++
题目描述 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。 小明想找到两个正整数 X 和 Y,满足2019<X<Y;2019^2, X^2, Y^2组成等差数列。 请你求出在所有可能的解中,XY 的最小值是多少?…...
vue中,给一个URL地址,利用FileSaver.js插件下载文件到本地
①首先下载 FileSaver.js 插件 npm install file-saver --save ②在需要的.vue页面引入 import { saveAs } from file-saver 在HTML中引入 <script src"https://cdn.bootcdn.net/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script> //Fil…...
从0开始学python -34
Python3 输入和输出-2 读和写文件 open() 将会返回一个 file 对象,基本语法格式如下: open(filename, mode)filename:包含了你要访问的文件名称的字符串值。mode:决定了打开文件的模式:只读,写入,追加等。…...
瑞典军事研究:从认知心理学的视角探讨军事创新进程
来源:Military Innovation as the Result of Mental Models of Technology 《摘要》 政治紧张局势的加剧和技术发展的进步促使Scandinavian 国家(斯堪的纳维亚半岛,欧洲最大的半岛,有挪威、瑞典两国以及芬兰北端的一小部分。&am…...
【MySQL进阶-08】深入理解innodb存储格式,双写机制,buffer pool底层结构和淘汰策略
MySql系列整体栏目 内容链接地址【一】深入理解mysql索引本质https://blog.csdn.net/zhenghuishengq/article/details/121027025【二】深入理解mysql索引优化以及explain关键字https://blog.csdn.net/zhenghuishengq/article/details/124552080【三】深入理解mysql的索引分类&a…...
5. AOP
一、如何定义一个MethodHandler? 1.Controller注解修饰的类 1.注册成Spring Bean 2.表示它是一个SpringMVC下的Controller 2.在这个类下的方法中,只要被RequestMapping修饰&&方法的形参符合规定(需要看文档) 方法的返回值符合规定…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
