前端實現(xiàn)HTML網(wǎng)頁轉(zhuǎn)PDF并導出
有個新需求,當點擊【下載】按鈕時,直接將當前 html頁面下載為 PDF。通過 html2canvas + jsPDF 可實現(xiàn)PDF單頁下載,甚至是多頁下載,記錄分享一下~ 最后有源碼,可自取

html2canvas
html2canvas官網(wǎng)在這:html2canvas - Screenshots with JavaScript
html2canvas 是一個 HTML 渲染器。該腳本允許你直接在用戶瀏覽器截取頁面或部分網(wǎng)頁的“屏幕截屏”,通過讀取 DOM 以及應用于元素的不同樣式,將當前頁面呈現(xiàn)為 canvas 圖像
安裝 html2canvas
npm install --save html2canvas
截取頁面生成canvas,并將其插入頁面中
html2canvas(document.body}).then(function(canvas) {
document.body.appendChild(canvas);
});注意:受限于瀏覽器的實現(xiàn),HTML 的 canvas 元素也有高度限制 可參考 canvas 最大畫布尺寸 - MDN
- Chrome 和 Firefox 等現(xiàn)代瀏覽器,canvas 的最大尺寸通常限制在 32767 像素,這也是 WebGL 和 2D canvas 的共同限制。超過這個值會導致 canvas 生成失敗,拋出錯誤,或者顯示空白內(nèi)容。
- 老版本的 IE 對 canvas 尺寸限制較為嚴格,一般在 8192 像素上下。現(xiàn)代版本的 Edge 則與 Chrome 的限制類似
jsPDF
jsPDF文檔可以看這:GitHub - parallax/jsPDF: Client-side JavaScript PDF generation for everyone.
安裝 jspdf
npm install jspdf --save
API也很簡單,下面是個生成文本和圖片的PDF樣例
// jsPDF 下載文本圖片PDF
const downLoadPdf = () => {
// 三個參數(shù),第一個方向,第二個單位,第三個尺寸 'a4' = [595.28,841.89]
const doc = new jsPDF('', 'pt', [500, 1000])
// 字體大小
doc.setFontSize(50)
// 文本,左邊距,上邊距
doc.text('Hello world!', 10, 50)
// base64,圖片類型,左邊距,上邊距,寬度,高度
doc.addImage(base64, 'PNG', 10, 60, 400, 200)
doc.save('a4.pdf')
}注意: jsPDF 生成的 PDF 默認以 pt (point) 為單位,單頁的最大高度通常限制在 14400 pt。超過這個高度可能導致生成的 PDF 無法正確渲染或瀏覽器崩潰?
html2canvas + jsPDF 實現(xiàn)頁面下載
單頁下載(自適應紙)
PDF頁面的寬高 采用 canvas的寬高
- 若
canvas.height >= canvas.width,采用portrait縱向頁面 - 若
canvas.width > canvas.height,采用landscape橫向頁面
如果頁面很長的話,單頁下載就會生成一張長長的PDF。注意!超過限制就會顯示空白頁面, jsPDF 生成的 PDF單頁最大高度為 14400pt
canvas也有最大高度限制 32767像素,如果頁面過長的話,通過 html2canvas 生成 canvas會失敗
const downLoadPdfAutoSingle = () => {
html2canvas(document.body, {
scale: window.devicePixelRatio * 2, // 使用設備的像素比 * 2
}).then(canvas => {
// 返回圖片dataURL,參數(shù):圖片格式和清晰度(0-1)
const pageData = canvas.toDataURL('image/jpeg', 1.0)
const pageWidth = canvas.width
const pageHeight = canvas.height
const orientation = canvas.height >= canvas.width ? 'portrait' : 'landscape' // portrait 表示縱向,landscape表示橫向
const pdf = new jsPDF(orientation, 'pt', [pageWidth, pageHeight])
// addImage后兩個參數(shù)控制添加圖片的尺寸,此處將頁面高度按照a4紙寬高比列進行壓縮
pdf.addImage(
pageData,
'JPEG',
0,
0,
pageWidth,
pageHeight
)
pdf.save('下載一頁PDF(自適應紙).pdf')
})
}單頁下載(A4紙)
已知:A4紙的寬度 和 canvas的寬度高度??傻?canvas在A4紙上占用的總高度(A4紙尺寸為寬 595.28pt,高 841.89pt)
如果頁面很長的話,單頁下載就會生成一張長長的PDF。注意!超過限制就會顯示空白頁面, jsPDF 生成的 PDF單頁最大高度為 14400pt
canvas也有最大高度限制 32767像素,如果頁面過長的話,通過 html2canvas 生成 canvas會失敗
const downLoadPdfA4Single = () => {
html2canvas(document.body).then(canvas => {
// 返回圖片dataURL,參數(shù):圖片格式和清晰度(0-1)
const pageData = canvas.toDataURL('image/jpeg', 1.0)
// 方向縱向,尺寸ponits,紙張格式 a4 即 [595.28, 841.89]
const A4Width = 595.28
const A4Height = 841.89 // A4紙寬
const pageHeight = A4Height >= A4Width * canvas.height / canvas.width ? A4Height : A4Width * canvas.height / canvas.width
const pdf = new jsPDF('portrait', 'pt', [A4Width, pageHeight])
// addImage后兩個參數(shù)控制添加圖片的尺寸,此處將頁面高度按照a4紙寬高比列進行壓縮
pdf.addImage(
pageData,
'JPEG',
0,
0,
A4Width,
A4Width * canvas.height / canvas.width,
)
pdf.save('下載一頁PDF(A4紙).pdf')
})
}多頁下載(自適應紙)
由于 jsPDF 單頁最大高度的限制 又或是 需求層面,我們需要實現(xiàn)自動分頁下載
我們設置一頁PDF頁面寬度為canvas.width,高度為canvas.width * 1.3
分頁思路:每個PDF頁面都顯示一張 canvas 圖,只不過是計算偏移量,每個PDF頁面顯示的是 canvas 的不同位置
問題來了,如何創(chuàng)建一個新的PDF頁面呢?可以使用 jsPDF 的pdf.addPage()
const downLoadPdfAutoMultiple = () => {
const ele = document.body
html2canvas(ele, {
scale: window.devicePixelRatio * 2, // 使用設備的像素比 * 2
}).then(canvas => {
let position = 0 //頁面偏移
const autoWidth = canvas.width // 一頁紙寬度
const autoHeight = canvas.width * 1.3 // 一頁紙高度
// 一頁PDF可顯示的canvas高度
const pageHeight = (canvas.width * autoHeight) / autoWidth
// 未分配到PDF的canvas高度
let unallottedHeight = canvas.height
// canvas對應的PDF寬高
const imgWidth = canvas.width
const imgHeight = canvas.height
const pageData = canvas.toDataURL('image/jpeg', 1.0)
const pdf = new jsPDF('', 'pt', [autoWidth, autoHeight])
// 當canvas高度 未超過 一頁PDF可顯示的canvas高度,無需分頁
if (unallottedHeight <= pageHeight) {
pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
pdf.save('下載多頁PDF(自適應紙).pdf')
return
}
while (unallottedHeight > 0) {
pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
unallottedHeight -= pageHeight
position -= autoHeight
if (unallottedHeight > 0) {
pdf.addPage()
}
}
pdf.save('html2canvas+jsPDF下載PDF.pdf')
})
}多頁下載(A4紙)
由于 jsPDF 單頁最大高度的限制 又或是 需求層面,我們需要實現(xiàn)自動分頁下載
我們設置一頁PDF頁面的寬高為A4紙尺寸,即寬 595.28pt,高 841.89pt
分頁思路:每個PDF頁面都顯示一張 canvas 圖,只不過是計算偏移量,每個PDF頁面顯示的是 canvas 的不同位置
問題來了,如何創(chuàng)建一個新的PDF頁面呢?可以使用 jsPDF 的pdf.addPage()
const downLoadPdfA4Multiple = () => {
const ele = document.body
html2canvas(ele, {
scale: 2, // 使用設備的像素比
}).then(canvas => {
let position = 0 //頁面偏移
const A4Width = 595.28 // A4紙寬度
const A4Height = 841.89 // A4紙寬
// 一頁PDF可顯示的canvas高度
const pageHeight = (canvas.width * A4Height) / A4Width
// 未分配到PDF的canvas高度
let unallottedHeight = canvas.height
// canvas對應的PDF寬高
const imgWidth = A4Width
const imgHeight = (A4Width * canvas.height) / canvas.width
const pageData = canvas.toDataURL('image/jpeg', 1.0)
const pdf = new jsPDF('', 'pt', [A4Width, A4Height])
// 當canvas高度 未超過 一頁PDF可顯示的canvas高度,無需分頁
if (unallottedHeight <= pageHeight) {
pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
pdf.save('下載多頁PDF(A4紙).pdf')
return
}
while (unallottedHeight > 0) {
pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
unallottedHeight -= pageHeight
position -= A4Height
if (unallottedHeight > 0) {
pdf.addPage()
}
}
pdf.save('下載多頁PDF(A4紙).pdf')
})
}源碼
GitHub - burc-li/vue-pdf: HTML 轉(zhuǎn) PDF下載(html2canvas 和 jsPDF實現(xiàn))
到此這篇關于前端實現(xiàn)HTML網(wǎng)頁轉(zhuǎn)PDF并導出的文章就介紹到這了,更多相關HTML網(wǎng)頁轉(zhuǎn)PDF內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
基于JavaScript實現(xiàn)實時在線協(xié)作編輯器
隨著Web技術的發(fā)展,實現(xiàn)在線協(xié)作編輯文檔已經(jīng)成為一種常見的需求,本文主要為大家詳細介紹了如何使用JavaScript實現(xiàn)實時在線協(xié)作編輯器,需要的可以參考下2024-01-01
在IE和VB中支持png圖片透明效果的實現(xiàn)方法(vb源碼打包)
在IE和VB中支持png圖片透明效果的實現(xiàn)方法(vb源碼打包),需要的朋友可以參考下。2011-04-04
javascirpt實現(xiàn)2個iframe之間傳值的方法
這篇文章主要介紹了javascirpt實現(xiàn)2個iframe之間傳值的方法,涉及javascript針對iframe框架下的頁面元素操作技巧,具有一定參考借鑒價值,需要的朋友可以參考下2016-06-06

