一行代码将html页面转成矢量PDF

非标题党,真的一行代码就可以实现纯前端 html 转矢量 pdf 的功能

javascript 复制代码
// 引入 dompdf.js库
import dompdf from "dompdf.js";

dompdf(document.querySelector("#capture")).then(function (blob) {
  //文件操作
});

实现效果(复杂表格)

1. 在线体验

dompdfjs.lisky.com.cn

2. Git 仓库地址 (欢迎 Star⭐⭐⭐)

github.com/lmn1919/dom...

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。

具体可以去体验 立即体验 https://dompdfjs.lisky.com.cn

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,提优化,共建项目。

相关推荐
m0_738120729 小时前
应急响应——知攻善防Web-3靶机详细教程
服务器·前端·网络·安全·web安全·php
hh随便起个名15 小时前
力扣二叉树的三种遍历
javascript·数据结构·算法·leetcode
我是小路路呀16 小时前
element级联选择器:已选中一个二级节点,随后又点击了一个一级节点(仅浏览,未确认选择),此时下拉框失去焦点并关闭
javascript·vue.js·elementui
程序员爱钓鱼16 小时前
Node.js 编程实战:文件读写操作
前端·后端·node.js
PineappleCoder16 小时前
工程化必备!SVG 雪碧图的最佳实践:ID 引用 + 缓存友好,无需手动算坐标
前端·性能优化
JIngJaneIL17 小时前
基于springboot + vue古城景区管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
敲敲了个代码17 小时前
隐式类型转换:哈基米 == 猫 ? true :false
开发语言·前端·javascript·学习·面试·web
澄江静如练_17 小时前
列表渲染(v-for)
前端·javascript·vue.js
JustHappy18 小时前
「chrome extensions🛠️」我写了一个超级简单的浏览器插件Vue开发模板
前端·javascript·github