🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付

一個AI都無法提供的html轉PDF方案

企業微信截圖_20251011152750.png

這也許就是AI無法代替人的原因,只需一行代碼就可以實現純前端 html 轉矢量 pdf 的功能

// 引入 dompdf.js庫
import dompdf from "dompdf.js";

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

實現效果(複雜表格)

企業微信截圖_20251011173729.png

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, 比如包含表格、圖片、圖表等內容,那使用成本就更高了。

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("粉紅色矩形", 25, 108);

  doc.setFillColor(173, 216, 230);
  doc.rect(100, 90, 60, 30, "F");
  doc.text("淺藍色矩形", 105, 108);

  doc.save("chinese-example.pdf");
}

但是現在,有了 dompdf.js,你只需要一行代碼,就可以完成比這個複雜 10 倍的 PDF 生成任務,html頁面所見即所得,可以將複雜的css樣式轉化成pdf

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. 使用

安裝

npm install dompdf.js --save

CDN 引入

<script src="https://cdn.jsdelivr.net/npm/dompdf.js@latest/dist/dompdf.js"></script>

基礎用法

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,提優化,共建專案。


原文出處:https://juejin.cn/post/7559886023661649958


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝22   💬9   ❤️6
601
🥈
我愛JS
📝4   💬14   ❤️7
271
🥉
御魂
💬1  
3
#4
2
#5
1
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付