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

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

目录
相关文章
|
1天前
|
存储 前端开发 JavaScript
前端基础(二)_JavaScript变量、JavaScript标识符、JavaScript获取元素、JavaScript的鼠标事件
本文介绍了JavaScript变量的声明和使用、标识符的命名规则、如何获取和操作HTML元素,以及JavaScript的鼠标事件处理,通过示例代码展示了这些基础知识点在实际开发中的应用。
9 2
前端基础(二)_JavaScript变量、JavaScript标识符、JavaScript获取元素、JavaScript的鼠标事件
|
1天前
|
JavaScript 前端开发
JavaScript HTML DOM
JavaScript HTML DOM
7 2
JavaScript HTML DOM
|
1天前
|
前端开发
前端基础(十四)_隐藏元素的方法
本文介绍了几种在前端开发中隐藏元素的方法,包括使用`display:none`、`visibility:hidden`、`opacity:0`等CSS属性,并提供了相应的示例代码。此外,还提到了其他隐藏元素的技巧,如通过设置元素位置、使用`overflow`属性和`filter`属性以及`rgba`颜色值来实现元素的隐藏。
12 1
前端基础(十四)_隐藏元素的方法
|
1天前
|
前端开发 JavaScript
前端基础(七)_DOM元素获取(getElementById、getElementsByTagName、getElementsByClassName、querySelector等)
本文介绍了如何在前端通过不同的方法获取DOM元素,包括getElementById、getElementsByTagName、getElementsByClassName、querySelector和querySelectorAll。
8 3
|
1天前
|
JavaScript 前端开发
前端基础(十)_Dom自定义属性(带案例)
本文介绍了DOM自定义属性的概念和使用方法,并通过案例展示了如何使用自定义属性来控制多个列表项点击变色的独立状态。
6 0
前端基础(十)_Dom自定义属性(带案例)
|
1月前
|
XML 缓存 JSON
为什么浏览器中有些图片、PDF等文件点击后有些是预览,有些是下载
为什么浏览器中有些图片、PDF等文件点击后有些是预览,有些是下载
142 0
|
1月前
|
Linux Python Windows
Python PDF文件转Word格式,只需要3秒(附打包)
Python PDF文件转Word格式,只需要3秒(附打包)
58 3
Python PDF文件转Word格式,只需要3秒(附打包)
pdf文件转化为png照片 (PyMuPDF下面的fitz)
pdf文件转化为png照片 (PyMuPDF下面的fitz)
|
29天前
|
移动开发 资源调度 JavaScript
Vue移动端网页(H5)预览pdf文件(pdfh5和vue-pdf)
这篇文章介绍了在Vue移动端网页中使用`pdfh5`和`vue-pdf`两个插件来实现PDF文件的预览,包括滚动查看、缩放、添加水印、分页加载、跳转指定页数等功能。
107 0
Vue移动端网页(H5)预览pdf文件(pdfh5和vue-pdf)
|
1月前
|
JSON JavaScript 数据格式
打印插件 hiprint 使用、回单打印PDF保存本地、将列表数据打印成pdf文件保存到本地
这篇文章介绍了如何使用hiprint打印插件将列表数据打印成PDF文件并保存到本地,包括插件的配置、依赖安装、项目代码案例以及如何预览和打印数据。
打印插件 hiprint 使用、回单打印PDF保存本地、将列表数据打印成pdf文件保存到本地