当前位置: 首页 > news >正文

使用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失败")});

效果:
在这里插入图片描述

http://www.lryc.cn/news/11472.html

相关文章:

  • 云环境渗透测试的重要性
  • ROS2 入门应用 请求和应答(Python)
  • 是德Keysight E4991A/e4991B射频阻抗/材料分析仪
  • 这才是计算机科学_人工智能
  • DFS深度优先搜索—Java版
  • RAY - 小记
  • 金三银四软件测试工程师面试题(含答案)
  • Python 连接数据源与邮件功能(九)
  • 网站如何锁定用户,超级浏览器有办法解决吗?
  • Ubuntu下使用Wine运行HBuilderX
  • 如何高效远程维护分布在海外的中大型智能设备?
  • 【双指针问题】LeetCode 925. 长按键入
  • APP测试中IOS和Android的区别,有哪些注意点?
  • 2019蓝桥杯真题平方序列(填空题) C语言/C++
  • vue中,给一个URL地址,利用FileSaver.js插件下载文件到本地
  • 从0开始学python -34
  • 瑞典军事研究:从认知心理学的视角探讨军事创新进程
  • 【MySQL进阶-08】深入理解innodb存储格式,双写机制,buffer pool底层结构和淘汰策略
  • 5. AOP
  • ubuntu上尝试libpqxx库链接人大金仓
  • 【Python入门第十二天】Python 列表
  • Android 异步操作库 RxJava
  • 2021-12-05青少年软件编程(C语言)等级考试试卷(六级)解析
  • github 使用
  • Kubernetes集群维护—备份恢复与升级
  • 前端开发常用案例(二)
  • 基于springboot+vue的儿科保健计划免疫系统
  • 1.两数之和
  • 字符串匹配 - 模式预处理:KMP 算法(Knuth-Morris-Pratt)
  • 工程师手册:电源设计中的电容选用规则