html2canvas导出PDF遇横向滚动条内容截断,如何完整显示?
解决html2canvas导出PDF内容截断问题
问题描述
使用html2canvas将ID为to_print的div导出为PDF时,网页端可完整显示内容,但生成的PDF出现右侧内容截断的情况。当前使用的导出代码和HTML结构如下:
导出代码
function printPdf() { var w = document.getElementById("to_print").offsetWidth; var h = document.getElementById("to_print").offsetHeight; html2canvas(document.getElementById("to_print"), { dpi: 300, scale: 3, onrendered: function(canvas) { var img = canvas.toDataURL("image/jpeg", 1); var doc = new jsPDF('L', 'px', [w, h]); doc.addImage(img, 'JPEG', 0, 0, w, h); doc.save('rapport-arrivee-depart.pdf'); } }); }
HTML结构
<div id="to_print"> <div class="row"> <div class="col-md-12" style="background-color: white"> <div class="portlet box green"> <div class="portlet-title"> <div class="caption"> <i class="fa fa-globe"></i><fmt:message key="HOTEL.REPORT_ARRIVAL_DEPARTURE.PAGE_BREADCRUMB.SPAN"/> </div> <div class="tools"> </div> </div> <div class="portlet-body"> <table class="table table-striped table-bordered table-hover" id="sample_1"> <thead> <tr> <th colspan="3"></th> <th class="uppercase text-center" colspan="3"><fmt:message key="COMMON.DEPARTURE.TITLE"/></th> <th class="uppercase text-center" colspan="3"><fmt:message key="COMMON.ARRIVED.TITLE"/></th> <th colspan="2"></th> </tr> <tr role="row"> <th class="uppercase text-center"> <fmt:message key="COMMON.NUM.CHAMBER_MIN"/> </th> <th class="uppercase text-center"> <fmt:message key="COMMON.TYPE.TITLE"/> </th> <th class="uppercase text-center"> <fmt:message key="COMMON.REPORT.TITLE"/> </th> <th class="uppercase text-center"> <fmt:message key="COMMON.TABLE.NAME_MIN"/> </th> <th class="uppercase text-center"> <fmt:message key="COMMON.ADULT_CHILD.TITLE"/> </th> <th class="uppercase text-center"> <fmt:message key="COMMON.CHILD.TITLE"/> </th> <th class="uppercase text-center"> <fmt:message key="COMMON.TABLE.NAME_MIN"/> </th> <th class="uppercase text-center"> <fmt:message key="COMMON.ADULT_CHILD.TITLE"/> </th> <th class="uppercase text-center"> <fmt:message key="COMMON.CHILD.TITLE"/> </th> <th class="uppercase text-center"> <fmt:message key="COMMON.HOUR.TITLE"/> </th> <th class="uppercase text-center"> <fmt:message key="COMMON.NUMBER.NIGHT"/> </th> </tr> </thead> <tbody> </tbody> <tfoot> <tr> <th class="uppercase text-center"></th> <th class="uppercase text-center"></th> <th class="uppercase text-center"></th> <th class="uppercase text-center"></th> <th style="text-align:center"></th> <th class="uppercase text-center"></th> <th class="uppercase text-center"></th> <th style="text-align:center"></th> <th class="uppercase text-center"></th> <th class="uppercase text-center"></th> <th class="uppercase text-center"></th> </tr> </tfoot> </table> </div> </div> </div> </div> <div class="row invoice-subtotal right" style="background-color: white"> <div class="col-xs-3 col-xs-offset-3"> <strong><fmt:message key="HOTEL.REPORT_ARRIVAL_DEPARTURE.NUMBER_BEDROOM_DEPARTURE"/> : <span id="bindNbDepart"><fmt:message key="COMMON.NOT.DEFINED"/></span></strong> </div> <div class="col-xs-3"> <strong><fmt:message key="HOTEL.REPORT_ARRIVAL_DEPARTURE.NUMBER_BEDROOM_ARRIVAL"/> : <span id="bindNbArrivee"><fmt:message key="COMMON.NOT.DEFINED"/></span></strong> </div> </div> </div>
解决方案
1. 修正元素尺寸获取逻辑
offsetWidth仅返回元素的可见宽度,当内容存在横向溢出(比如表格过宽)时,无法获取完整的内容宽度。改用scrollWidth获取元素的完整滚动宽度,同时用getBoundingClientRect()获取更精准的尺寸:
const element = document.getElementById("to_print"); const rect = element.getBoundingClientRect(); const fullWidth = element.scrollWidth; // 完整内容宽度 const fullHeight = rect.height; // 元素实际高度
2. 调整html2canvas配置
确保html2canvas捕获完整的元素内容,添加scrollX: 0、scrollY: 0避免滚动偏移,同时替换已废弃的onrendered为Promise语法(适配新版html2canvas):
html2canvas(element, { dpi: 300, scale: 3, scrollX: 0, scrollY: 0, useCORS: true // 若有跨域图片需开启 }).then(canvas => { // 后续PDF生成逻辑 });
3. 优化jsPDF的尺寸与缩放
避免直接使用px单位,改用更适合PDF的pt,同时计算内容与PDF页面的适配比例,确保完整显示:
// 获取canvas的实际尺寸 const canvasWidth = canvas.width; const canvasHeight = canvas.height; // 设置PDF为横向A4纸 const pdf = new jsPDF('l', 'pt', 'a4'); const pdfPageWidth = pdf.internal.pageSize.getWidth(); const pdfPageHeight = pdf.internal.pageSize.getHeight(); // 计算缩放比例,取宽高中较小的比例确保内容适配 const scaleFactor = Math.min(pdfPageWidth / canvasWidth, pdfPageHeight / canvasHeight); const scaledWidth = canvasWidth * scaleFactor; const scaledHeight = canvasHeight * scaleFactor; // 居中放置内容 const xPos = (pdfPageWidth - scaledWidth) / 2; const yPos = (pdfPageHeight - scaledHeight) / 2; // 添加图片到PDF pdf.addImage(canvas.toDataURL("image/jpeg", 1), 'JPEG', xPos, yPos, scaledWidth, scaledHeight); pdf.save('rapport-arrivee-depart.pdf');
完整优化后的代码
function printPdf() { const element = document.getElementById("to_print"); const rect = element.getBoundingClientRect(); const fullWidth = element.scrollWidth; const fullHeight = rect.height; html2canvas(element, { dpi: 300, scale: 3, scrollX: 0, scrollY: 0, useCORS: true }).then(canvas => { const canvasWidth = canvas.width; const canvasHeight = canvas.height; // 使用A4横向纸张 const pdf = new jsPDF('l', 'pt', 'a4'); const pdfPageWidth = pdf.internal.pageSize.getWidth(); const pdfPageHeight = pdf.internal.pageSize.getHeight(); // 计算适配比例 const scaleFactor = Math.min(pdfPageWidth / canvasWidth, pdfPageHeight / canvasHeight); const scaledWidth = canvasWidth * scaleFactor; const scaledHeight = canvasHeight * scaleFactor; // 居中放置内容 const xPos = (pdfPageWidth - scaledWidth) / 2; const yPos = (pdfPageHeight - scaledHeight) / 2; pdf.addImage(canvas.toDataURL("image/jpeg", 1), 'JPEG', xPos, yPos, scaledWidth, scaledHeight); pdf.save('rapport-arrivee-depart.pdf'); }).catch(err => { console.error('导出PDF失败:', err); }); }
额外建议
- 如果表格内容极长,可考虑分页处理:通过计算内容高度与PDF页面高度的比例,拆分canvas为多个页面添加到PDF中。
- 确保
html2canvas和jsPDF使用最新版本,避免旧版本的兼容性问题。
内容的提问来源于stack exchange,提问作者pheromix
相关产品推荐
相关产品推荐

