使用html-to-image代替html2canvas,结合jspdf实现下载pdf(下载截图下载前端dom元素)

news2024/11/16 6:00:17

一、问题

一开始的时候,准备使用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.coloradmin.cn/o/351662.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

map和set介绍及其底层模拟实现

致努力前行的人&#xff1a; 要努力&#xff0c;但不要着急&#xff0c;繁花锦簇&#xff0c;硕果累累都需要过程&#xff01; 目录 1.关联式容器 2.键值对 3.树形结构的关联式容器 3.1set的介绍 3.2set的使用 3.3multiset的使用 3.4map的使用 3.5multimap的使用 4.常见的面试题…

【Ctfshow_Web】信息收集和爆破

0x00 信息收集 web1 直接查看源码 web2 查看不了源码&#xff0c;抓包即可看到&#xff08;JS拦截了F12&#xff09; web3 抓包&#xff0c;发送repeater&#xff0c;在响应包中有Flag字段 web4 题目提示后台地址在robots&#xff0c;访问/robots.txt看到Disallow: /fl…

vite结合ts使用mock模拟数据,实现前后端异步开发

vite结合ts&#xff0c;vue3 使用mock模拟数据&#xff0c;实现前后端异步开发 第一步&#xff1a;安装依赖 安装mock&#xff1a;npm install mockjs --save-dev安装vite-mock插件&#xff1a;npm install vite-plugin-mock --save 注解1&#xff1a; npm 安装依赖包的时候…

消息中间件----内存数据库 Redis7(第3章 Redis 命令)

Redis 根据命令所操作对象的不同&#xff0c;可以分为三大类&#xff1a;对 Redis 进行基础性操作的命令&#xff0c;对 Key 的操作命令&#xff0c;对 Value 的操作命令。3.1 Redis 基本命令首先通过 redis-cli 命令进入到 Redis 命令行客户端&#xff0c;然后再运行下面的命令…

2023年浙江建筑八大员(市政质量员)考试试题题库及答案

百分百题库提供建筑八大员&#xff08;质量员&#xff09;考试试题、建筑八大员&#xff08;质量员&#xff09;考试预测题、建筑八大员&#xff08;质量员&#xff09;考试真题、建筑八大员&#xff08;质量员&#xff09;证考试题库等,提供在线做题刷题&#xff0c;在线模拟考…

如何在 Debian 11 上设置一个静态 IP 地址

当你在电脑上安装一个新的操作系统时&#xff0c;DHCP服务器会给你分配一个动态IP地址。然而&#xff0c;在各种情况下&#xff0c;你可能需要在你的机器上设置一个静态IP地址&#xff0c;例如&#xff0c;当你正在托管一个网络服务器&#xff0c;或者任何服务需要一个IP地址而…

K_A12_007 基于STM32等单片机驱动AS608光学指纹识别模块 OLED0.96显示

K_A12_007 基于STM32等单片机驱动AS608光学指纹识别模块 OLED0.96显示一、资源说明二、基本参数参数引脚说明三、驱动说明对应程序:四、部分代码说明1、接线引脚定义1.1、STC89C52RCAS608光学指纹模块1.2、STM32F103C8T6AS608光学指纹模块五、基础知识学习与相关资料下载六、视…

【自学Linux】Linux一切皆文件

Linux一切皆文件 Linux一切皆文件教程 Linux 中所有内容都是以文件的形式保存和管理的&#xff0c;即一切皆文件&#xff0c;普通文件是文件&#xff0c;目录是文件&#xff0c;硬件设备&#xff08;键盘、监视器、硬盘、打印机&#xff09;是文件&#xff0c;就连套接字&…

小红书数据平台:笔记爆文率提升的三大秘诀公式!

导语 对于小红书商家 / 博主来说&#xff0c;写出爆文就像买彩票&#xff0c;根本不能预知哪一篇会爆。2023年&#xff0c;小红书哪些内容会脱颖而出呢&#xff1f;我们又该如何把握热点趋势&#xff0c;实现优质内容转化出爆文~ 美妆作为小红书的长红赛道&#xff0c;本文我…

如何停止/重启/启动Redis服务

一、命令行直接启动/停止/重启redis 可以直接通过下面的命令启动/停止/重启redis /etc/init.d/redis-server start 启动redis服务 /etc/init.d/redis-server stop 停止redis服务 /etc/init.d/redis-server restart 重启redis服务1、启动redis服务…

BUUCTF-firmware1

题目下载&#xff1a;下载 新题型&#xff0c;记录一下 题目给出了flag形式&#xff0c;md5{网址&#xff1a;端口}&#xff0c;下载发现是一个.bin文件 二进制文件&#xff0c;其用途依系统或应用而定。一种文件格式binary的缩写。一个后缀名为".bin"的文件&#x…

40/365 javascript 数据类型

1.数据类型 number类型&#xff1a;整数&#xff0c;小数都属于这一类&#xff0c;不具体区分 字符串&#xff1a;hello, "hello" 布尔类型&#xff1a;true,false 逻辑运算符&#xff1a; && || ! 比较运算符&#xff1a; : 类型不一致&#x…

openGauss数据库共享存储特性简介

openGauss 3.1.1是openGauss 5.0.0 release版本的Preview版本&#xff0c;希望广大社区伙伴和开发者基于此版本进行场景化验证&#xff0c;提前发现问题并反馈社区&#xff0c;社区将在LTS版本发布前进行问题修复。当前文档说明范围仅限企业版。 文章目录版本介绍继承功能&…

轻松在 MAUI 应用中播放音视频,MediaElement 现已发布!

最受期待的 .NET MAUI 控件之一&#xff1a;MediaElement 现已发布。有了 MediaElement&#xff0c;您可以轻松地在 .NET MAUI 应用程序中播放音频和视频&#xff0c;在这篇文章中&#xff0c;您将了解到有关 MediaElement 第一个版本的所有信息以及我们对未来的计划&#xff0…

8086汇编-35更灵活定位内存地址04

#pragma once/*35-更灵活定位内存地址04不同的寻址方式的灵活应用如果我们比较一下前面用到的几种定位内存地址的方法&#xff08;可称为寻址方式&#xff09;&#xff0c;就可以发现有以下几种方式&#xff1a;&#xff08;1&#xff09;[idata] 用一个常量来表示地址&#xf…

新房装修流程详细步骤有哪些? 新房装修流程注意事项有哪些?

新房装修时&#xff0c;对于装修流程的详细步骤和装修过程中的一些注意事项&#xff0c;有必要了解一下&#xff0c;以免上当受骗&#xff0c;也免得考虑不周&#xff0c;后续造成一些隐患。新房装修流程详细步骤有哪些呢&#xff1f;1.新装装修流程第一步&#xff0c;首先&…

Java_Maven:4. maven 私服

目录 1 需求 2 分析 3 搭建私服环境 3.1 下载 nexus 3.2 安装 nexus 3.3 卸载 nexus 3.4 启动 nexus 3.5 仓库类型 4 将项目发布到私服 4.1 需求 4.2 配置 4.3 测试 5 从私服下载 jar 包 5.1 需求 5.2 管理仓库组 5.3 在 setting.xml 中配置仓库 5.4 测试从私…

C++之迭代器

迭代器C中&#xff0c;迭代器就是类似于指针的对象&#xff0c;但比指针的功能更丰富&#xff0c;它提供了对对象的间接访问&#xff0c;每个迭代器对象代表容器中一个确定的地址。举个例子&#xff1a;void test() {vector<int> vv{1,2,3,4,5};for(vector<int>::i…

大数据框架之Hadoop:MapReduce(一)MapReduce概述

1.1MapReduce定义 MapReduce是一个分布式计算框架&#xff0c;用于编写批处理应用程序&#xff0c;是用户开发“基于Hadoop的数据分析应用”的核心框架。 MapReduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序&#xff0c;并发运行在一…

一文掌握如何对项目进行诊断?【步骤方法和工具】

作为项目经理和PMO&#xff0c;面对错综复杂的项目&#xff0c;需要对组织的项目运作情况进行精确的分析和诊断&#xff0c;找出组织项目管理中和项目运行中存在的问题和潜在隐患&#xff0c;分析其原因&#xff0c;预防风险&#xff0c;并且形成科学合理的决策建议和解决方案&…