使用html2Cancas和jspdf将前端页面进行截图导出PDF,内容被截断的问题

使用两个库html2Cancas和jspdf,分别用于将html元素转换为Canvas和将Canvas转为pdf文件。

html部分:

demo为要导出的部分

<div id="demo" ref="report">

//.........页面内容

</div>

js部分:

import JsPDF from "jspdf";
import html2Canvas from "html2canvas";





// 存储各个分页的留白高度
let zancunH = [];

// 判断节点是否被分割
function isSplit(nodes, index, pageHeight) {
  if (nodes[index].offsetTop + nodes[index].scrollHeight < pageHeight && nodes[index + 1] && nodes[index + 1].offsetTop + nodes[index + 1].scrollHeight > pageHeight) {
    return true; // 节点被分割
  } else {
    return false; // 节点未被分割
  }
}

// 输出PDF方法
function outPutPdfFn() {
  // 将页面滚动条置顶
  document.body.scrollTop = 0;
  document.body.scrollLeft = 0;

  // A4纸张宽度和高度
  const A4_WIDTH = 592.28;
  const A4_HEIGHT = 841.89;

  // 获取图片容器和页面高度
  let imageWrapper = document.getElementById('demo');
  let pageHeight = (imageWrapper.scrollWidth / A4_WIDTH) * A4_HEIGHT;

  // 获取所有需要分割的节点
  let lableListID = imageWrapper.querySelectorAll('.sign');

  // 初始化分页留白数组
  zancunH[0] = 0;

  // 遍历节点,判断是否需要分割并添加留白节点
  for (let i = 0; i < lableListID.length; i++) {
    let multiple = Math.ceil((lableListID[i].offsetTop + lableListID[i].scrollHeight) / pageHeight);
    if (isSplit(lableListID, i, multiple * pageHeight)) {
      let divParent = lableListID[i].parentNode; // 获取节点的父节点
      let newNode = document.createElement('div');
      newNode.className = 'emptyDiv';
      newNode.style.background = '#ffffff';
      let _H = multiple * pageHeight - (lableListID[i].offsetTop + lableListID[i].scrollHeight);
      zancunH[multiple] = _H;
      newNode.style.height = _H + 'px'; // 设置留白节点高度
      newNode.style.width = '100%';
      let next = lableListID[i].nextSibling; // 获取节点的下一个兄弟节点
      if (next) {
        divParent.insertBefore(newNode, next); // 将留白节点插入到下一个兄弟节点之前
      } else {
        divParent.appendChild(newNode); // 将留白节点添加到最后
      }
    }
  }

  // 使用html2Canvas进行截图
html2Canvas(imageWrapper, { // 使用html2Canvas进行截图
  allowTaint: true, // 允许跨域图片渲染
  x: imageWrapper.getBoundingClientRect().left + 13, // 绘制的 dom 元素相对于视口的左边距加上偏移量
  y: imageWrapper.getBoundingClientRect().top, // 绘制的 dom 元素相对于视口的上边距
  width: imageWrapper.offsetWidth - 15, // 绘制的 dom 元素的宽度减去15像素
  height: imageWrapper.offsetHeight, // 绘制的 dom 元素的高度
  backgroundColor: '#FFF', // 绘制的背景颜色设置为白色
  useCORS: true, // 使用跨域资源
  scale: 3, // 图片放大倍数,提高清晰度
  dpi: 350, // 设置图片的 dpi(每英寸像素数)
})
    .then((canvas) => {
      // 使用jsPDF生成PDF
      let pdf = new JsPDF('p', 'mm', 'a4'); // 创建A4大小的PDF
      let ctx = canvas.getContext('2d');
      let a4w = 190;
      let a4h = 270; // A4 大小,210mm x 297mm,四边各保留 10mm 的边距,显示区域 190x277,
      let imgHeight = Math.floor((a4h * canvas.width) / a4w);  // 按 A4显示比例换算一页图像的像素高度
      let renderedHeight = 0;

      // 按照A4大小进行分页渲染
      while (renderedHeight < canvas.height) {
        let page = document.createElement('canvas');
        page.width = canvas.width;
        page.height = Math.min(imgHeight, canvas.height - renderedHeight); // 可能内容不足一页
        // 用 getImageData 剪裁指定区域,并画到前面创建的 canvas 对象中
        page
          .getContext('2d')
          .putImageData(ctx.getImageData(0, renderedHeight, canvas.width, Math.min(imgHeight, canvas.height - renderedHeight)), 0, 0);
        pdf.addImage(page.toDataURL('image/jpeg', 0.2), 'JPEG', 10, 10, a4w, Math.min(a4h, (a4w * page.height) / page.width)); // 添加图像到页面,保留 10mm 边距
        renderedHeight += imgHeight;
        if (renderedHeight < canvas.height) pdf.addPage(); // 如果后面还有内容,添加一个空页
      }
      pdf.save('paperDownName'); // 下载PDF文件
    })
    .then(() => {
      // 下载成功提示
      ElMessage({
        message: '文件下载成功',
        type: 'success',
      });
    })
    .catch((error) => {
      // 下载失败提示
      console.error('PDF 文件保存失败:', error);
      ElMessage.error('文件下载失败');
    });
}

在进行截图时可能会出现被内容被截断的情况,通过上方的插入空白元素的方法还是会存在文字截断的问题。

通过对比pdf中每页的内容以及页面中空白元素插入的位置,发现pdf分页的位置并不是空白元素插入的位置,而是比空白元素的插入的位置再要往下一点,此时可减小在创建JsPDF时所设置的A4大小的高度,或加大初始时的pageHeight,减小两者之间的差距,从而使得pdf的截断位置和插入空白元素的位置相同。这也是在代码中a4的值(270)与注释中的值(277)不一样的原因。

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: HTML2Canvas是一个将HTML DOM元素转换为canvas的JavaScript库,而jspdf是一个用于生成PDF文档的JavaScript库。因此,您可以使用HTML2Canvas将HTML DOM元素转换为Canvas,然后使用jspdf将Canvas转换为PDF。 要处理分页图片和被截断的文本问题,您可以使用以下步骤: 1. 将HTML DOM元素转换为Canvas。您可以使用HTML2Canvas库来完成此操作。请确保在转换时包含所有的分页图片和文本。 2. 将所有的Canvas合并在一起,以便生成单个PDF文件。您可以使用canvas.toDataURL()方法将每个Canvas转换为图像数据URL。然后,将所有的图像数据URL合并在一起,并使用jspdf将它们转换为PDF。 3. 处理被截断的文本。如果文本被截断,您可以使用CSS的white-space属性来处理它。例如,您可以设置white-space:pre-wrap属性来打破单词并允许文本换行。 4. 处理分页图片。如果您有分页图片,您可以将它们分成多个Canvas,并将它们一起合并到PDF中。这将确保每个分页图片都在正确的位置显示。 总的来说,使用HTML2Canvas和jspdf生成PDF文档是一个十分强大的工具。通过遵循上述步骤,您可以轻松地处理文本被截断和分页图片的问题,并生成高质量的PDF文件。 ### 回答2: html2canvas是一个javascript库,用于将HTML元素渲染为Canvas,并提供了将Canvas导出为图片的功能。而jspdf是另一个javascript库,用于生成PDF文件使用html2canvas和jspdf可以实现在前端生成PDF文件的功能。首先,使用html2canvas将HTML页面内容渲染为Canvas。然后,将Canvas转换为图像数据,并将图像数据添加到jspdfPDF文件中。最后,可以将生成PDF文件保存或下载。 但是在处理分页时,把整个HTML页面转换为Canvas,可能会导致图片和文字被截断问题。这是因为Canvas在渲染时有大小限制。 为了解决这个问题,可以通过在特定位置手动分页来控制页面内容的展示。首先,确定每一页需要展示的内容,并在对应的位置手动分页。具体的做法是使用CSS的page-break属性来设置页面的分页位置,以确保每一页不会出现图片和文字被截断的情况。 在使用html2canvas时,可以通过设置ignoreElements属性来忽略某些元素不进行渲染,以避免被截断。例如,对于需要分页的图片,可以在转换为Canvas时,将其设置为忽略的元素,保证图片完整显示在各个页面中。 总而言之,使用html2canvas和jspdf可以在前端实现PDF文件生成,但处理分页时需要注意图片和文字被截断问题。通过手动设置分页位置和忽略特定元素,可以解决这个问题,确保生成PDF文件中的内容完整可读。 ### 回答3: html2canvas是一个JavaScript库,可以将HTML元素转换为canvas画布,并且可以配合jspdf生成PDF文件。 要处理分页图片和文字被截断问题,可以按照以下步骤进行: 1. 引入html2canvas和jspdf库。 2. 创建一个用于生成PDF的按钮或者其他触发事件。 3. 使用html2canvas库将需要转换为PDFHTML元素转换为canvas画布。可以使用html2canvas()方法,并将需要转换的元素传递给该方法。 4. 使用toDataURL()方法将canvas画布转换为一个base64编码的图像字符串。 5. 创建一个jspdf实例。可以使用`new jsPDF()`创建一个新的jspdf实例。 6. 使用jspdf的addImage()方法将之前生成的base64编码的图像字符串添加到页面上。可以通过指定x、y坐标和图像的宽度和高度来设置图像在PDF中的位置和尺寸。 7. 使用jspdf的save()方法保存生成PDF文件。 对于分页图片和文字被截断问题html2canvas和jspdf并不能自动处理。可以通过以下方法来解决: 1. 对于图片,可以在将HTML元素转换为canvas之前,通过调整元素的尺寸、位置或者裁剪来确保图片完整显示在一个页面中。 2. 对于文字,可以通过调整元素的字体大小、行高或者缩减内容来确保文字完整显示在一个页面中。 3. 如果需要处理多页的情况,可以使用循环或者递归的方式将分页的内容分别转换为canvas,并通过jspdf的addPage()方法在PDF中添加新的页面。 总结来说,通过html2canvas和jspdf配合使用,可以在前端生成PDF文件。对于处理分页图片和文字被截断问题,需要手动调整HTML元素的尺寸、位置和内容,以确保完整显示在PDF中。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值