You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用jsPDF+html2canvas生成PDF时圆形Div分页截断问题求助

问题

使用jsPDF结合html2canvas生成并下载PDF时,页面中一个设置为圆形、内部带数值的Div会被分页截断,部分内容分属两页。希望让这个Div整体移至下一页,避免被截断。当前使用的下载代码如下:

downloadPDF(): void {
const buttons = document.querySelectorAll('.button-content');
buttons.forEach((button) => {
  (button as HTMLElement).style.display = 'none';
});

const content = document.getElementById('pdf-content');
if (content) {
  html2canvas(content, { scale: 2, useCORS: true }).then((canvas) => {
    const imgWidth = 210;
    const pageHeight = 295;
    const imgHeight = (canvas.height * imgWidth) / canvas.width;
    let heightLeft = imgHeight;

    const doc = new jsPDF('p', 'mm', 'a4');
    let position = 0;

    doc.addImage(
      canvas.toDataURL('image/png'),
      'PNG',
      0,
      position,
      imgWidth,
      imgHeight,
    );
    heightLeft -= pageHeight;

    while (heightLeft >= 0) {
      position = heightLeft - imgHeight;
      doc.addPage();
      doc.addImage(
        canvas.toDataURL('image/png'),
        'PNG',
        0,
        position,
        imgWidth,
        imgHeight,
      );
      heightLeft -= pageHeight;
    }

    doc.save('Maturity Assessment Result Report.pdf');

    buttons.forEach((button) => {
      (button as HTMLElement).style.display = 'inline-block';
    });
  });
}
}
解决方案

你当前的做法是把整个页面内容转成一张大画布再切割成A4页面,这种方式无法识别元素边界,自然会出现元素被截断的情况。以下是几种可行的解决思路:

方法1:使用html2pdf库(推荐)

html2pdf基于jsPDF和html2canvas开发,内置分页控制功能,可通过配置避免指定元素被截断。

先安装依赖:

npm install html2pdf.js

修改下载函数:

downloadPDF(): void {
  const buttons = document.querySelectorAll('.button-content');
  buttons.forEach((button) => {
    (button as HTMLElement).style.display = 'none';
  });

  const content = document.getElementById('pdf-content');
  if (content) {
    // 配置选项,替换`.circle-div`为你的圆形Div类名
    const opt = {
      margin: 10,
      filename: 'Maturity Assessment Result Report.pdf',
      image: { type: 'png', quality: 0.98 },
      html2canvas: { scale: 2, useCORS: true },
      jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' },
      pagebreak: { mode: ['avoid-all', 'css'], before: '.circle-div' }
    };

    html2pdf().set(opt).from(content).save();

    buttons.forEach((button) => {
      (button as HTMLElement).style.display = 'inline-block';
    });
  }
}

pagebreak配置会在指定元素前自动分页,确保它完整显示在一页中。

方法2:手动计算元素位置调整布局

如果不想引入新库,可在生成canvas前手动计算圆形Div的位置,判断是否跨页,若跨页则插入空白元素将其推到下一页。

示例代码片段:

// 在调用html2canvas前执行以下逻辑
const circleDivs = document.querySelectorAll('.circle-div');
const pdfPageHeight = 295; // 你的PDF页面高度(mm)
const contentWidth = content.offsetWidth;
const scale = 210 / contentWidth; // 页面宽度转PDF宽度的比例

circleDivs.forEach(div => {
  const rect = div.getBoundingClientRect();
  const contentRect = content.getBoundingClientRect();
  // 计算元素在内容区的相对顶部位置(px)
  const relativeTop = rect.top - contentRect.top;
  // 转换为PDF中的位置(mm)
  const pdfTop = relativeTop * scale;
  // 计算元素在PDF中的底部位置
  const pdfBottom = pdfTop + (rect.height * scale);
  // 判断是否跨页
  const currentPage = Math.floor(pdfTop / pdfPageHeight);
  const bottomPage = Math.floor(pdfBottom / pdfPageHeight);
  
  if (currentPage !== bottomPage) {
    // 插入空白div将元素推到下一页
    const spacer = document.createElement('div');
    const remainingSpace = (currentPage + 1) * pdfPageHeight - pdfTop;
    const spacerHeight = remainingSpace / scale;
    spacer.style.height = `${spacerHeight}px`;
    div.parentNode.insertBefore(spacer, div);
  }
});

// 之后再调用html2canvas生成PDF

方法3:逐个元素添加到jsPDF

放弃整体转canvas的方式,手动遍历页面元素逐个添加到jsPDF中。这种方式能精确控制每个元素的位置,遇到圆形Div时检查当前页面剩余空间,不够则新建页面再添加。适合结构不复杂的页面,但需要处理文本、图片、样式等细节,控制度最高。


内容的提问来源于stack exchange,提问作者Presha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 20:55:13