html2pdf-exporter
v1.0.0
Published
一个强大的HTML转PDF工具,支持分页、页眉页脚、自定义布局等功能
Maintainers
Readme
HTML2PDF 工具
功能介绍
HTML2PDF 是一个强大的 HTML 转 PDF 工具,用于将网页内容转换为高质量的 PDF 文档。该工具基于 jsPDF 和 html2canvas 库,解决了以下常见问题:
- 大型内容分页处理:自动处理超出单页的内容,确保内容不会被截断
- 页眉页脚支持:支持自定义页眉页脚,并可在每页显示页码
- 精确布局控制:提供丰富的配置选项,控制 PDF 的布局、边距和内容宽度
- 自定义分页:通过 CSS 类控制元素的分页行为
- 跨页元素处理:智能处理表格、图片等跨页元素
- iframe 内容处理:尝试渲染同源 iframe 内容,对跨域 iframe 提供占位符
- 高性能渲染:针对大型文档进行了性能优化
- 进度回调:支持导出进度实时反馈
安装
NPM
npm install html2pdf-exporterYarn
yarn add html2pdf-exporter依赖
本工具依赖以下库:
npm install jspdf html2canvas基本用法
简单示例
import { createPDF } from 'html2pdf-exporter';
// 基本用法
const exportPDF = async () => {
const element = document.getElementById('content-to-export');
const pdf = createPDF(element);
await pdf.toPdf('导出文档.pdf');
};添加页眉页脚
import { createPDF } from 'html2pdf-exporter';
const exportWithHeaderFooter = async () => {
const element = document.getElementById('content-to-export');
const header = document.getElementById('pdf-header');
const footer = document.getElementById('pdf-footer');
const pdf = createPDF(element);
// 设置页眉
pdf.header(header);
// 设置页脚(需要包含页码元素)
pdf.footer(footer, {
// 可选:自定义页码选择器
pageNumSelector: '.pdf-page-num',
pageTotalSelector: '.pdf-page-total'
});
await pdf.toPdf('带页眉页脚的文档.pdf');
};高级配置
设置内容宽度和边距
const pdf = createPDF(element);
// 设置内容宽度(默认550,A4纸宽度为595.28)
pdf.contentWidth(500);
// 设置边距
pdf.margin({
left: 30, // 左边距
right: 30, // 右边距
top: 20, // 上边距
bottom: 20 // 下边距
});设置页面方向和背景色
const pdf = createPDF(element);
// 设置为横向(landscape)
pdf.changeOrientation('l');
// 设置页面背景色
pdf.setPageBackgroundColor('#f5f5f5');
// 设置内容区域背景色
pdf.setContentBackgroundColor('#ffffff');监听导出进度
const pdf = createPDF(element);
// 设置进度回调
pdf.onProgress((currentPage, totalPages) => {
console.log(`导出进度: ${currentPage}/${totalPages}`);
// 更新进度条
const progress = Math.floor((currentPage / totalPages) * 100);
document.getElementById('progress-bar').style.width = `${progress}%`;
});CSS 类控制分页行为
通过在 HTML 元素上添加特定的 CSS 类,可以控制元素在 PDF 中的分页行为:
| CSS 类 | 说明 |
| ------ | ---- |
| pdf-break-page | 在该元素前强制分页 |
| pdf-not-calc-height | 叶子节点,允许跨页但不计算子元素 |
| pdf-not-calc-height-group | 叶子节点,不允许跨页(空间不够时整体移到下一页) |
| pdf-scroll | 有滚动条的元素,会先移除滚动效果全部展开,渲染后再恢复 |
| pdf-footer-page | 页脚中显示当前页码的元素 |
| pdf-footer-page-total | 页脚中显示总页数的元素 |
示例:
<!-- 强制分页 -->
<div class="pdf-break-page">新的一页内容</div>
<!-- 表格行,不允许跨页 -->
<tr class="pdf-not-calc-height-group">
<td>数据1</td>
<td>数据2</td>
</tr>
<!-- 页脚 -->
<div id="pdf-footer">
第 <span class="pdf-footer-page">1</span> 页,共 <span class="pdf-footer-page-total">10</span> 页
</div>自定义分页控制
对于复杂的分页需求,可以使用过滤器来控制元素的分页行为:
const pdf = createPDF(element);
// 设置叶子节点过滤器(整体跨页,不遍历子元素)
pdf.setClassControlFilter('isLeafWithoutDeepFilter', (className) => {
return className.includes('table-row') || className.includes('card-item');
});
// 设置深度叶子节点过滤器(整体跨页,但会遍历子元素)
pdf.setClassControlFilter('isLeafWithDeepFilter', (className) => {
return className.includes('section') || className.includes('chapter');
});完整示例
import { createPDF } from 'html2pdf-exporter';
export async function exportReport() {
try {
// 显示加载状态
const loadingEl = document.getElementById('loading');
loadingEl.style.display = 'block';
// 获取要导出的元素
const content = document.getElementById('report-content');
const header = document.getElementById('report-header');
const footer = document.getElementById('report-footer');
// 创建PDF实例
const pdf = createPDF(content);
// 配置PDF
pdf.contentWidth(550)
.margin({ top: 20, bottom: 20 })
.header(header, { skipPage: 1 }) // 第一页不显示页眉
.footer(footer)
.setPageBackgroundColor('#ffffff')
.setStyleCheck(true)
.forcePageTotal(true) // 强制计算总页数
.onProgress((current, total) => {
const percent = Math.floor((current / total) * 100);
document.getElementById('progress').innerText = `${percent}%`;
});
// 导出PDF
await pdf.toPdf('业务报表.pdf');
// 隐藏加载状态
loadingEl.style.display = 'none';
} catch (error) {
console.error('PDF导出失败', error);
alert('导出失败,请重试');
}
}注意事项
样式限制:
- PDF 不支持
z-index,元素叠加顺序取决于 DOM 结构 - 部分 CSS 效果(如阴影、渐变)可能无法完美呈现
- PDF 不支持
大型内容:
- 对于非常大的内容(高度超过 32,000 像素),建议设置
forcePageTotal(true)以正确计算总页数 - 对于复杂表格,建议使用
pdf-not-calc-height-group类避免行被截断
- 对于非常大的内容(高度超过 32,000 像素),建议设置
跨域资源:
- 导出包含跨域图片或资源的内容时,需要确保这些资源支持 CORS
- 跨域 iframe 内容无法导出,会显示占位符
性能优化:
- 导出大型文档时,可以使用
setStyleCheck(false)关闭样式检查提高性能 - 考虑分段导出特别大的文档
- 导出大型文档时,可以使用
浏览器兼容性:
- 该工具在现代浏览器(Chrome、Firefox、Edge、Safari)中表现良好
- 不支持 IE 浏览器
许可证
MIT
