iT邦幫忙

2026 iThome 鐵人賽

DAY 26
0
Software Development

從零打造網頁簡報編輯器系列 第 26 篇

Day 26|把研究分享簡報輸出成 PDF

  • 分享至 

  • xImage
  •  

系列:一張投影片背後的工程:從零打造網頁簡報編輯器

對應程式:2026-10-04 工作目錄,package.json 版本 0.20.0;不是 v0.4.0 的歷史操作紀錄。

今天要交付的是一個可以帶走的檔案。我沿用上一篇的研究分享簡報:第一頁有中文與一張合成長條圖,第二頁整理分享方式,第三頁是略過的補充資料;前兩頁另外保存只有講者需要的備註。

最後產生的 PDF 應有兩頁。觀眾能看到標題和圖表,卻不該看到編輯工具、第三頁或講者備註。

https://ithelp.ithome.com.tw/upload/images/20261006/20182759XOlOYMAjIM.png

2026-10-04 的實際列印 DOM 截圖,使用與 PDF 相同的列印樣式;這張圖不是原生列印對話框,也不是 PDF 檔案的轉圖。圖表為合成示意資料。

先把交付條件寫清楚

簡報裡的內容 交付時要看到什麼
三張投影片,其中一張略過 列印頁面與 PDF 都只有兩頁
中文標題與 PNG 圖表 字型準備完成,圖片成功解碼
講者備註 留在可編輯文件,排除於投影片輸出
淡入轉場、選取框與工具列 固定頁面中不出現這些互動效果

本次自動化確實產生 demo-two-slides.pdf,檢查到兩個 PDF 頁面;輸出前也確認列印 DOM 的中文標題存在、圖片可解碼、備註和補充頁已排除。這些是不同層次的檢查,不能只看檔案副檔名就算成功。

列印前等待的是內容準備完成

使用者按「輸出 PDF」時,程式先呼叫 preparePrint(),等待列印頁面可用,再開啟瀏覽器列印對話框。主要流程是:

if (document.fonts) await document.fonts.ready

// 等待 IndexedDB 圖片讀取完成;這段設有五秒期限。
while (root.querySelector('.image-placeholder.is-loading')) {
  // 檢查期限,稍後再查詢。
}

const images = Array.from(root.querySelectorAll('img'))
await Promise.allSettled(images.map((image) => image.decode()))

字型準備與圖片解碼是兩件事。DOM 裡已經有文字或 img,不代表排版與圖像都準備好。字型等待使用 document.fonts.ready,圖片則先等資產讀取佔位消失,再等 decode()。MDN:FontFaceSet.ready、HTMLImageElement.decode()

目前仍有一個明確限制:五秒期限只管「圖片還在讀取」的佔位,沒有包住字型等待或全部解碼。Promise.allSettled() 也會容許解碼失敗,因此產品流程仍可能進入含破圖的列印畫面。

本次取證腳本採用較嚴格的 Promise.all(images.map(img => img.decode())),有圖片解碼失敗就中止。這能確保示範素材通過檢查,並不表示產品已經有同樣的失敗處理。

一張投影片對應一張紙

列印頁採用約 16:9 的 13.333in × 7.5in,邊界設為零。1600 × 900 的邏輯畫布以 0.8 倍放入頁面;換算後是 1280 × 720 CSS px,約等於上述尺寸。

每頁都使用 break-after: page,最後一頁改成 auto,避免尾端多出空白頁。投影片本身的固定尺寸與列印分頁在這裡各負責一件事,不必重新計算每個物件的位置。

@page {
  size: 13.333in 7.5in;
  margin: 0;
}

.print-page:last-child {
  break-after: auto;
  page-break-after: auto;
}

這裡只是節錄,完整尺寸與列印專用規則放在 src/styles.css。印出來的 PDF 也不會保存播放轉場。

自動產生 PDF,與使用者按另存 PDF

這次腳本透過 Edge 的 Page.printToPDF 產生檔案,保留背景並採用 CSS 頁面尺寸。使用者操作產品時,走的仍是 window.print() 與瀏覽器的「另存成 PDF」。

window.print() 會開啟列印對話框,但不會回報使用者最後選擇儲存或取消。因此程式不能在函式返回後顯示「PDF 已成功儲存」。MDN:Window.print()

自己操作時,可按以下順序確認:

  1. 按「輸出 PDF」,在列印目的地選擇另存 PDF。
  2. 查看預覽是否兩頁,確認中文、圖片、背景與頁面邊界。
  3. 關閉不需要的頁首頁尾,確認設定沒有覆蓋預期版面。
  4. 儲存後重新開啟 PDF,確認第二頁完整、沒有第三張補充頁。

這四步是讀者的人工重現方式。本次新增的是瀏覽器自動化與檔案證據,沒有把人工對話框驗收登記成已通過。


上一篇
Day 25|讓簡報支援全螢幕、黑畫面與轉場
下一篇
Day 27|用批次格式與格式刷統一簡報樣式
系列文
從零打造網頁簡報編輯器 共 29 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言