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

使用jsPDF生成PDF时元素重叠、顺序与预览不一致如何解决?

jsPDF生成PDF元素重叠混乱修复方案

问题根因

jsPDF本身是画布类工具,不具备浏览器的流式自动排版能力,你仅按顺序调用渲染API但没有手动指定每个元素的坐标位置,所有元素默认都从页面左上角(0,0)位置开始渲染,自然会出现重叠、顺序混乱的问题。

修复思路

手动维护一个Y轴偏移量变量,每完成一个元素的渲染后,更新该偏移量为当前元素的底部位置,下一个元素从该偏移量位置开始渲染,即可保证元素按顺序排列不重叠。

核心修改点

  • 定义初始Y轴偏移量,预留页面边距
  • 每个渲染API都传入对应X/Y坐标参数
  • 利用autoTable提供的lastAutoTableFinalY属性自动获取表格渲染结束位置,无需手动计算表格高度
  • 对图片做等比缩放适配PDF页面尺寸

完整修改后可运行代码

<!DOCTYPE html>
<html lang="en">
 <head>
   <meta charset="UTF-8" />
   <meta name="viewport" content="width=device-width, initial-scale=1.0" />
   <title>Test</title>
   <style>
     #output {
       width: 100%;
       height: 100vh;
       margin-top: 20px;
     }
     #my-table {
       border: solid 1px #565656;
       border-collapse: collapse;
       font-family: helvetica,serif;
       font-size: 10pt;
       width: 180mm;
     }
     #my-table th {
       border: solid 1px #565656;
       background-color: #9a7f5b;
       color: #eee;
       text-align: left;
       padding: 5px;
     }
     #my-table td {
       border: solid 1px #565656;
       padding: 2px 5px;
     }
   </style>
   <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
   <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.5/jspdf.min.js"></script>
   <script src="https://unpkg.com/jspdf-autotable"></script>
 </head>
 <body>
 <!--ELEMENTS PDF-->
   <h1 id="title">This is a test</h1>
   <p id="text">Lorem ipsum dolor sit amet consectetur adipisicing elit. Blanditiis natus ipsa sit ab ipsum illum vero dolore velit impedit debitis itaque aut, magni ut laborum ratione esse? Beatae, omnis excepturi.</p>
   <table id="my-table">
     <thead>
       <tr>
         <th>ID</th>
         <th colspan="2">Name</th>
         <th>Email</th>
         <th>Country</th>
         <th>Activity</th>
       </tr>
     </thead>
     <tbody>
       <tr>
         <td>1</td>
         <td>Donna</td>
         <td>Moore</td>
         <td>Example.com</td>
         <td>China</td>
         <td>Work</td>
       </tr>
       <tr>
         <td>2</td>
         <td>Janice</td>
         <td>Henry</td>
         <td>Example.com</td>
         <td>Ukraine</td>
         <td>Eat</td>
       </tr>
       <tr>
         <td>3</td>
         <td>Ruth</td>
         <td>Wells</td>
         <td>Example.com</td>
         <td>Mexico</td>
         <td>Run</td>
       </tr>
       <tr>
         <td>4</td>
         <td>Jason</td>
         <td>Ray</td>
         <td>Example.com</td>
         <td>Brazil</td>
         <td>Commute</td>
       </tr>
       <tr>
         <td>5</td>
         <td>Jane</td>
         <td>Stephens</td>
         <td>Example.com</td>
         <td>United States</td>
         <td>Watch TV</td>
       </tr>
       <tr>
         <td>6</td>
         <td>Adam</td>
         <td>Nichols</td>
         <td>Example.com</td>
         <td>Canada</td>
         <td>Sleep</td>
       </tr>
     </tbody>
   </table>
   <div id="piechart" style="width: 600px; height: 300px; margin: 35px 0px 0px 40px;"></div>
 <!--^ ELEMENTS PDF ^-->
   <script type="text/javascript">
     google.charts.load('current', {'packages':['corechart']}
     ).then(function () {
      //Google Charts
       var data = google.visualization.arrayToDataTable([
         ['Task', 'Hours per Day'],
         ['Work',     11],
         ['Eat',      2],
         ['Commute',  2],
         ['Watch TV', 2],
         ['Sleep',    7]
       ]);
       var chartpie = new google.visualization.PieChart(document.getElementById('piechart'));
       chartpie.draw(data);

       //------------------jsPDF ------------------
       const doc = new jsPDF('p', 'mm')
       // 定义初始边距和Y轴偏移量
       const leftMargin = 10;
       let yOffset = 10;
       const pageWidth = doc.internal.pageSize.getWidth();
       const contentWidth = pageWidth - leftMargin * 2;

       // 渲染标题
       doc.fromHTML(document.getElementById('title'), leftMargin, yOffset);
       yOffset += 15; // 标题高度+下边距

       // 渲染正文
       doc.fromHTML(document.getElementById('text'), leftMargin, yOffset, { width: contentWidth });
       yOffset += 25; // 正文高度+下边距

       // 渲染表格
       doc.autoTable({
           html: '#my-table',
           theme: 'grid',
           startY: yOffset,
           margin: { left: leftMargin, right: leftMargin }
       })
       // 自动获取表格结束位置
       yOffset = doc.lastAutoTableFinalY + 10;

       // 渲染饼图,等比缩放
       const imgWidth = contentWidth;
       const imgHeight = 300 * imgWidth / 600; // 原图宽高比600:300
       doc.addImage(chartpie.getImageURI(), 'PNG', leftMargin, yOffset, imgWidth, imgHeight);

       doc.save('example.pdf');
     });
   </script>
 </body>
</html>

无需挂载DOM的实现方法

无需挂载DOM即可完成PDF生成,对应API用法如下:

  • 文本内容直接调用doc.text('文本内容', x, y)渲染,无需提前写在HTML里
  • 表格不用指定html选择器,直接给autoTable传columns表头数组和body表格内容数组即可
  • 图片直接传base64格式的内容到addImage方法,不需要先在页面渲染图表DOM

错误效果参考

错误效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 03:27:02