dompdf.js
1. 文档概述
核心内容: dompdf.js - 一个前端生成 PDF 的解决方案,可在浏览器中直接将 HTML 生成为真正的、非图片式、可编辑的、高清晰度的 PDF 文件。
2. 资源链接
- GitHub 仓库: dompdf.js
3. 技术方案对比分析
现有 PDF 生成方案对比
| 方案类型 | 优点 | 缺点 |
|---|---|---|
| Puppeteer 等无头浏览器 | ✅ 渲染效果与浏览器完全一致 ✅ 支持 JavaScript 动态内容 | ❌ 资源消耗大(内存、CPU) ❌ 启动速度慢 ❌ 并发处理能力有限 ❌ 需要服务器环境 |
| jsPDF/PDFKit | ✅ 纯前端实现,无服务器依赖 ✅ 文件体积小 ✅ 生成速度快 ✅ 支持矢量图形 | ❌ 需要手动构建 PDF 结构 ❌ 不支持复杂 HTML 布局 ❌ 学习成本较高 ❌ 样式支持有限 |
| PDFMake | ✅ 纯前端解决方案 ✅ 声明式 API,易于使用 ✅ 支持表格、图表等 ✅ 模板化程度高 | ❌ 不支持 HTML 直接转换 ❌ 需要重新构建文档结构 ❌ 样式定制能力有限 ❌ 复杂布局实现困难 |
| html2canvas + jsPDF | ✅ 实现简单 ✅ 纯前端方案 ✅ 所见即所得 | ❌ 生成图片式 PDF,无法编辑 ❌ 文件体积大 ❌ 清晰度不够 ❌ 不支持文字选择 |
| dompdf.js | ✅ 纯前端实现 ✅ 快速上手,对代码入侵小 ✅ 文件体积小 ✅ 支持文字选择和编辑 ✅ 矢量图形,清晰度高 | ❌ 部分 CSS 属性支持有限 ❌ 复杂布局可能有差异 ❌ 浏览器兼容性要求 |
4. dompdf.js 实现原理
技术基础
dompdf.js 基于 html2canvas + jsPDF 实现,但进行了关键性改造。
html2canvas 原理解析
- 遍历 DOM 树: 从指定 DOM 节点开始,递归遍历所有子节点,构建渲染队列
- 计算样式: 调用
window.getComputedStyle()获取元素最终 CSS 属性值 - 构建渲染模型: 将 DOM 节点和计算样式包装成渲染对象
- 创建 Canvas 上下文: 在内存中创建 canvas 元素和 2D 渲染上下文
- 模拟浏览器绘制: 将 CSS 属性翻译成 Canvas API 调用
CSS 到 PDF 的 API 映射表
| CSS 属性 | Canvas API 调用 | jsPDF API 调用 |
|---|---|---|
| background-color | ctx.fillStyle + ctx.fillRect() | doc.setFillColor() + doc.rect(x, y, w, h, 'F') |
| border | ctx.strokeStyle + ctx.strokeRect() | doc.setDrawColor() + doc.rect(x, y, w, h, 'S') |
| color, font-family, font-size | ctx.fillStyle, ctx.font + ctx.fillText() | doc.setTextColor() + doc.setFont() + doc.text() |
| border-radius | 通过 arcTo() 或 bezierCurveTo() 创建剪切路径 | doc.roundedRect() 或通过 doc.lines() 绘制圆角路径 |
| image | ctx.addImage() | doc.addImage() |
dompdf.js 的核心创新
将 html2canvas 最后一步的 Canvas API 调用替换为 jsPDF API 调用,实现从 DOM 到可编辑 PDF 的直接转换。
5. 功能支持情况
| 功能 | 状态 | 说明 |
|---|---|---|
| 文本渲染 | ✅ | 支持基础文本内容渲染,font-family, font-size, font-style, font-variant, color 等,支持文字描边,不支持文字阴影 |
| 图片渲染 | ✅ | 支持网络图片,base64 图片,svg 图片 |
| 边框 | ✅ | 支持 border-width, border-color, border-style, border-radius |
| 背景 | ✅ | 支持背景颜色,背景图片,背景渐变 |
| canvas | ✅ | 支持渲染 canvas |
| svg | ✅ | 支持渲染 svg |
| 阴影渲染 | ✅ | 使用 foreignObjectRendering,支持边框阴影渲染 |
| 渐变渲染 | ✅ | 使用 foreignObjectRendering,支持背景渐变渲染 |
| 复杂表格 | ✅ | 支持复杂表格渲染 |
| iframe | ❌ | 暂不支持渲染 iframe |
| 分页 | ❌ | 暂不支持分页 |
6. 【图片 Demo-1】foreignObjectRendering 功能演示
位置: 第6章节 - 使用 foreignObjectRendering 渲染复杂表格,边框阴影,渐变
Demo 描述
展示如何使用 foreignObjectRendering 属性处理复杂样式效果,包括边框阴影和渐变背景。
功能说明
- 解决复杂表格、边框阴影、渐变等 PDF 难以直接绘制的情况
- 通过 SVG 的 foreignObject 将元素渲染成背景图插入 PDF
代码片段
<div style="width: 100px;height: 100px;" foreignObjectRendering>
<div style="width: 50px;height: 50px;border: 1px solid #000;box-shadow: 2px 2px 5px rgba(0,0,0,0.3);background: linear-gradient(45deg, #ff6b6b, #4ecdc4);">
这是一个div元素
</div>
</div>
技术注意事项
- foreignObject 渲染依赖浏览器实现,不同浏览器表现可能不同
- IE 浏览器完全不支持,推荐在 Chrome、Firefox、Edge 中使用
- 生成的图片会导致 PDF 文件体积变大
7. 使用指南
安装
npm install dompdf.js --save
基础用法
import dompdf from "dompdf.js";
dompdf(document.querySelector("#capture"), {
useCORS: true, //是否允许跨域
})
.then(function (blob) {
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "example.pdf";
document.body.appendChild(a);
a.click();
})
.catch(function (err) {
console.log(err, "err");
});
字体支持
// 引入字体文件
<script type="text/javascript" src="./SourceHanSansSC-Normal-Min-normal.js"></script>;
dompdf(document.querySelector("#capture"), {
useCORS: true, //是否允许跨域
fontConfig: {
fontFamily: "SourceHanSansSC-Normal-Min",
fontBase64: window.fontBase64,
},
})
.then(function (blob) {
// 下载逻辑同上
});
字体配置说明
- 需要将字体 TTF 文件转换为 base64 格式的 JS 文件
- 推荐使用思源黑体中文字体,体积较小
- 转换工具链接在文档中提供