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

简介: 本文介绍了在前端项目中,当使用`html2canvas`遇到问题时,如何使用`html-to-image`库作为替代方案,结合`jspdf`实现将DOM元素生成为PDF文件并提供下载。文章首先讨论了`html2canvas`可能遇到的问题,并提供了该库的使用示例代码。随后,详细介绍了`html-to-image`库的安装和使用方法,展示了如何将DOM元素转换为Canvas,再利用`jspdf`生成PDF文件。最后,文章通过示例代码说明了整个转换和下载的过程,并展示了效果截图。

一、问题

一开始的时候,准备使用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失败")
        });

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

目录
相关文章
|
19天前
|
前端开发 JavaScript
除了 jsPDF,还有哪些前端库可以用于生成 PDF?
【10月更文挑战第21天】这些前端库都有各自的特点和优势,你可以根据具体的项目需求、技术栈以及对功能的要求来选择合适的库。不同的库在使用方法、性能表现以及功能支持上可能会有所差异,需要根据实际情况进行评估和选择。
|
1月前
|
JavaScript 前端开发 编译器
吐血整理:纯前端如何实现批量dom转图片,并下载成压缩包
【10月更文挑战第2天】吐血整理:纯前端如何实现批量dom转图片,并下载成压缩包
47 2
|
2月前
|
前端开发
Twaver-HTML5基础学习(37)network导出图片并下载
本文介绍了如何在Twaver-HTML5中将network导出为图片并提供下载,主要通过将network转换为canvas对象,然后转换为base64编码的图片进行展示和下载。
36 5
|
30天前
|
JavaScript 前端开发 容器
Vue生成PDF文件攻略:html2canvas与jspdf联手,中文乱码与自动换行难题攻克
Vue生成PDF文件攻略:html2canvas与jspdf联手,中文乱码与自动换行难题攻克
75 0
|
2月前
|
前端开发
前端基础(二)_HTML常用标签(块级标签、行级标签、行块级标签)
本文详细介绍了HTML中的常用标签,包括块级标签(如`h1`至`h6`、`p`、`div`等)、行级标签(如`span`、`b`、`strong`、`i`、`em`、`sub`、`sup`、`del`、`a`等),以及行块级标签(如`img`)。文章解释了这些标签的用途、特点和基本用法,并通过示例代码展示了如何在HTML文档中使用它们。
111 1
|
2月前
|
前端开发 Windows
【前端web入门第一天】02 HTML图片标签 超链接标签 音频标签 视频标签
本文档详细介绍了HTML中的图片、超链接、音频和视频标签的使用方法。首先讲解了`&lt;img&gt;`标签的基本用法及其属性,包括如何使用相对路径和绝对路径。接着介绍了`&lt;a&gt;`标签,用于创建超链接,并展示了如何设置目标页面打开方式。最后,文档还涵盖了如何在网页中嵌入音频和视频文件,包括简化写法及常用属性。
50 13
|
3月前
|
Java 开发者 关系型数据库
JSF与AWS的神秘之旅:如何在云端部署JSF应用,让你的Web应用如虎添翼?
【8月更文挑战第31天】在云计算蓬勃发展的今天,AWS已成为企业级应用的首选平台。本文探讨了在AWS上部署JSF(JavaServer Faces)应用的方法,这是一种广泛使用的Java Web框架。通过了解并利用AWS的基础设施与服务,如EC2、RDS 和 S3,开发者能够高效地部署和管理JSF应用。文章还提供了具体的部署步骤示例,并讨论了使用AWS可能遇到的挑战及应对策略,帮助开发者更好地利用AWS的强大功能,提升Web应用开发效率。
64 0