使用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修饰&&方法的形参符合规定(需要看文档) 方法的返回值符合规定…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
