使用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
相关产品推荐
相关产品推荐

