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

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

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

六卿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值