非标题党,真的一行代码就可以实现纯前端 html 转矢量 pdf 的功能
javascript
// 引入 dompdf.js库
import dompdf from "dompdf.js";
dompdf(document.querySelector("#capture")).then(function (blob) {
//文件操作
});
实现效果(复杂表格)

1. 在线体验
2. Git 仓库地址 (欢迎 Star⭐⭐⭐)
3. 生成 PDF
在前端生态里,把网页内容生成 PDF 一直是一个常见但不简单的需求。从报表导出、小票生成、合同下载到打印排版,很多项目或多或少都会遇到。市面上常见的方案大致有以下几类:
-
服务端渲染 PDF(后端库如 wkhtmltopdf、PrinceXML 等)
-
客户端将 HTML 渲染为图片(如 html2canvas + jsPDF)然后再封装为 PDF
-
前端调用相关 pdf 生成库来生成 PDF(如 pdfmake,jspdf,pdfkit)
但是这些方案都有各自的局限性,
-
比如服务端渲染 PDF 对服务器资源要求高,需要后端参与。
-
html2canvas + jsPDF 需要将 html 内容渲染为图片,再将图片封装为 PDF,速度会比较慢,而且生成体积会比较大,内容会模糊,限制于 canvas 生成高度,不能生成超过 canvas 高度的内容。
-
而前端调用相关 pdf 生成库来生成 PDF 则需要对相关库有一定的了解,api 比较复杂,学习使用成本很高。
使用 jspdf 生成如图简单的 pdf

就需要如此复杂的代码,如果要生成复杂的 pdf, 比如包含表格、图片、图表等内容,那使用成本就更高了。
javascript
function generateChinesePDF() {
// Check if jsPDF is loaded
if (typeof window.jspdf === "undefined") {
alert("jsPDF library has not finished loading, please try again later");
return;
}
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
// Note: Default jsPDF does not support Chinese, this is just a demo
// In real projects you need to add Chinese font support
doc.setFontSize(16);
doc.text("Chinese Text Support Demo", 20, 30);
doc.setFontSize(12);
doc.text("Note: Default jsPDF does not support Chinese characters.", 20, 50);
doc.text("You need to add Chinese font support for proper display.", 20, 70);
// Draw some graphics for demonstration
doc.setFillColor(255, 182, 193);
doc.rect(20, 90, 60, 30, "F");
doc.setTextColor(0, 0, 0);
doc.text("Pink Rectangle", 25, 108);
doc.setFillColor(173, 216, 230);
doc.rect(100, 90, 60, 30, "F");
doc.text("Light Blue Rectangle", 105, 108);
doc.save("chinese-example.pdf");
}
但是现在,有了 dompdf.js,你只需要一行代码,就可以完成比这个复杂 10 倍的 PDF 生成任务,html页面所见即所得,可以将复杂的css样式转化成pdf
javascript
dompdf(document.querySelector("#capture")).then(function (blob) {
//文件操作
});
而且,dompdf.js 生成的 PDF 是矢量的,非图片式的,高清晰度的,文字可以选中、复制、搜索等操作(在支持的 PDF 阅读器环境下),区别于客户端将 HTML 渲染为图片(如 html2canvas + jsPDF)然后再封装为 PDF。
4. dompdf.js 是如何实现的?
其实 dompdf.js 也是基于 html2canvas+jspdf 实现的,但是为什么 dompdf.js 生成的 pdf 文件可以二次编辑,更清晰,体积小呢?
不同于普通的 html2canvas + jsPDF 方案,将 dom 内容生成为图片,再将图片内容用 jspdf 绘制到 pdf 上,这就导致了生成的 pdf 文件体积大,无法编辑,放大后会模糊。
html2canvas 原理简介
1. DOM 树遍历 html2canvas 从指定的 DOM 节点开始,递归遍历所有子节点,构建一个描述页面结构的内部渲染队列。
2. 样式计算 对每个节点调用 window.getComputedStyle()
获取最终的 CSS 属性值。这一步至关重要,因为它包含了所有 CSS 规则(内联、内部、外部样式表)层叠计算后的最终结果。
3. 渲染模型构建 将每个 DOM 节点和其计算样式封装成渲染对象,包含绘制所需的完整信息:位置(top, left)、尺寸(width, height)、背景、边框、文本内容、字体属性、层级关系(z-index)等。
4. Canvas 上下文创建 在内存中创建 canvas 元素,获取其 2D 渲染上下文(CanvasRenderingContext2D)。
5. 浏览器绘制模拟 按照 DOM 的堆叠顺序和布局规则,遍历渲染队列,将每个元素绘制到 Canvas 上。这个过程实质上是将 CSS 属性"翻译"成对应的绘制 API 调用:
CSS 属性 | 传统 Canvas API | dompdf.js 中的 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.drawImage() |
doc.addImage() |
核心创新:API 替换,底层是封装了 jsPDF 的 API dompdf.js 的关键突破在于改造了 html2canvas 的 canvas-renderer.ts
文件,将原本输出到 Canvas 的绘制 API 替换为 jsPDF 的 API 调用。这样就实现了从 DOM 直接到 PDF 的转换,生成真正可编辑、可搜索的 PDF 文件,而不是传统的图片格式。
目前实现的功能
1. 文字绘制 (颜色,大小) 2. 图片绘制 (支持 jpeg, png 等格式) 3. 背景,背景颜色 (支持合并单元格) 4. 边框,复杂表格绘制 (支持合并单元格) 5. canvas (支持多种图表类型) 6. svg (支持 svg 元素绘制) 7. 阴影渲染 (使用 foreignObjectRendering,支持边框阴影渲染) 8. 渐变渲染 (使用 foreignObjectRendering,支持背景渐变渲染)
7.使用
安装
bash
npm install dompdf.js --save
CDN 引入
html
<script src="https://cdn.jsdelivr.net/npm/dompdf.js@latest/dist/dompdf.js"></script>
基础用法
js
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");
});
写在最后
dompdf.js 让前端 PDF 生成变得前所未有的简单:无需后端、无需繁琐配置、一行代码即可输出矢量、可检索、可复制的专业文档。无论是简历、报告还是发票,它都能轻松胜任。 欢迎在你的项目中使用它 。
如果它帮到了你,欢迎去 github.com/lmn1919/dom... 点个 Star,提优化,共建项目。