Html轉PDF,前端JS實現Html頁面導出PDF(html2canvas+jspdf)
文章目錄
一、背景介紹
? 當我們在不想改變后端代碼的同時想是純html頁面導出PDF,那么(html2canvas+jspdf)就是無疑最好的選擇,導出時它不占用我們服務器的資源,而是由用戶本地自行執行js文件下載PDF,不占用我們系統的帶寬,所以這無非是最好的選擇方式。
二、疑問
1、為什么要使用html2canvas,單jspdf也能實現pdf下載?
? HTML2Canvas 和 jsPDF 是 JavaScript 庫,用于在瀏覽器中生成 PDF 文件。
? HTML2Canvas 用于將 HTML 元素渲染成圖像,可以將整個頁面或特定區域以圖像形式進行捕獲。這對于將復雜的 HTML 結構轉換為 PDF 格式非常有用,因為它可以捕獲 HTML 中的樣式、布局和圖像等細節。 jsPDF 是一個 PDF 生成庫,它允許你通過 JavaScript 代碼創建和編輯 PDF 文檔。與 HTML2Canvas 結合使用,你可以將 HTML 元素渲染成圖像,然后將圖像插入到 jsPDF 創建的 PDF 文檔中。 雖然單獨使用 jsPDF 也可以實現 PDF 下載,但是在某些情況下,使用 HTML2Canvas 可能更方便。例如,當你需要將整個頁面轉換為 PDF 或以圖像形式捕獲特定區域時,HTML2Canvas 提供了更靈活的選項。然后,你可以將 HTML2Canvas 生成的圖像插入到 jsPDF 中,進一步編輯和操作 PDF。 綜上所述,使用 HTML2Canvas 結合 jsPDF 可以更容易地將 HTML 轉換為 PDF,并提供更多靈活性和控制力。
三、所使用技術
html2canvas+jspdf
js引入:引入線上js直接使用
<!--pdf下載 -->
<script src="https://html2canvas.hertzen.com/dist/html2canvas.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js"></script>
<!--jquery 方便后續使用jquery原生函數,可不引入-->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
四、展示開始
1、效果展示
html頁面
下載成PDF
2、代碼部分
js引入:
<!--pdf下載 -->
<script src="https://html2canvas.hertzen.com/dist/html2canvas.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js"></script>
<!--jquery 方便后續使用jquery原生函數,可不引入-->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
整體流程:
- 先將頁面通過html2canvas轉換成圖片
- (jsPDF)將轉換成的圖片導出成PDF的形式
<!--pdf下載 -->
<script src="assets/js/jspdf/html2canvas.js"></script>
<script src="assets/js/jspdf/jspdf.umd.min.js"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>$('#downloadPDF').click(function() {console.log('開始下載PDF');htmlToPdf();});function htmlToPdf() {// 獲取HTML元素const element = document.getElementById("layout-wrapper");const options = {dpi: 192, //dpi屬性的值為192,表示圖像的分辨率scale: 2, //scale屬性的值為2,表示圖像的縮放比例。backgroundColor: "#F1F6FE" //backgroundColor屬性的值為"#F1F6FE",表示圖像的背景顏色。};// 將元素轉換為canvas對象html2canvas(element, options).then((canvas) => {var contentWidth = canvas.width; //獲取Canvas(上面元素id 'layout-wrapper')對象的寬度var contentHeight = canvas.height; //獲取Canvas(上面元素id 'layout-wrapper')對象的高度// 創建jsPDF對象 jsPDF = jspdf.jsPDF; //導入jsPDF庫,用于創建PDF文件const pdf = new jsPDF('1', 'pt', [contentWidth, contentHeight]); //創建一個新的PDF對象,參數包括頁面格式('1'表示A4紙張)、單位('pt')和頁面尺寸([contentWidth, contentHeight])var pageData = canvas.toDataURL('image/jpeg', 1.0); //將Canvas對象轉換為JPEG格式的數據,并將其存儲在pageData變量中。1.0表示圖片質量pdf.addImage(pageData, 'JPEG', 0, 0, contentWidth, contentHeight); //將JPEG格式的圖片添加到PDF文件中,圖片的左上角坐標為(0, 0),寬度為contentWidth,高度為contentHeightpdf.save("test.pdf");});}
</script>
3、參數說明
3.1、html2canvas常用參數
html2canvas
函數接受一些常用的參數,用于配置轉換后的 canvas 元素的行為和樣式。以下是一些常用的參數:
element
: 必需參數,表示需要轉換為 canvas 的 HTML 元素。width
和height
: 可選參數,分別表示轉換后的 canvas 元素的寬度和高度。如果不設置這些參數,則 canvas 元素會自動調整大小以適應所包含的 HTML 元素。scale
: 可選參數,表示 canvas 元素的比例。默認值為 1,表示 canvas 元素會保持原始大小。border
: 可選參數,表示 canvas 元素的邊框寬度。默認值為 0,表示沒有邊框。backgroundColor
: 可選參數,表示 canvas 元素的背景顏色。默認值為 “#ffffff”,表示白色。foregroundColor
: 可選參數,表示 canvas 元素的前景色顏色。默認值為 “#000000”,表示黑色。imageQuality
: 可選參數,表示轉換后的圖像的質量。默認值為 1,表示高質量。jsPDF
: 可選參數,表示需要使用的 jsPDF 對象。如果不設置這個參數,則不會將 canvas 轉換為 PDF 文件。
以下是一個使用 html2canvas
函數的示例,其中包含了上述參數:
html2canvas(document.getElementById("my-element"), {width: 800,height: 600,scale: 2,border: 1,backgroundColor: "#cccccc",foregroundColor: "#000000",imageQuality: 0.9,jsPDF: pdf
}).then(function(canvas) {// 處理轉換后的 canvas 元素
});
3.2、jsPDF常用參數
jsPDF 是一個用于創建 PDF 文件的 JavaScript 庫。以下是 jsPDF 常用的參數:
jsPDF('1', 'pt', [width, height])
: 創建一個新的 PDF 對象,其中'1'
表示 A4 紙張(l:豎向,p:橫向),'pt'
表示單位為 point,width
和height
分別表示頁面寬度和高度。pdf.setFont(font, size)
: 設置 PDF 文件的字體和大小。其中font
表示字體名稱,如'Helvetica'
或'Times'
,size
表示字體大小。pdf.setLineWidth(width)
: 設置 PDF 文件的線寬。其中width
表示線寬的像素值。pdf.drawLine(x1, y1, x2, y2)
: 在 PDF 文件中繪制一條直線。其中x1
、y1
和x2
、y2
分別表示直線的起點和終點坐標。pdf.drawRect(x, y, width, height)
: 在 PDF 文件中繪制一個矩形。其中x
、y
分別表示矩形左上角的坐標,width
和height
分別表示矩形的寬度和高度。pdf.drawText(text, x, y)
: 在 PDF 文件中繪制一段文本。其中text
表示要繪制的文本,x
和y
分別表示文本的左上角坐標。pdf.save('filename.pdf')
: 將 PDF 文件保存為指定的文件名。其中'filename.pdf'
表示要保存的 PDF 文件的文件名。pdf.addImage(imageData, type, x, y, width, height)
: 在 PDF 文件中添加一個圖像。其中imageData
表示圖像的數據,type
表示圖像的類型,如'JPEG'
或'PNG'
,x
、y
分別表示圖像左上角的坐標,width
和height
分別表示圖像的寬度和高度。pdf.rotate(angle, x, y)
: 旋轉 PDF 文件中的圖像或文本。其中angle
表示旋轉的角度,x
和y
分別表示旋轉中心的位置。pdf.translate(x, y)
: 將 PDF 文件中的文本或圖像移動到指定位置。其中x
和y
分別表示要移動的坐標。
五、常見問題
1、圖片跨域
解決方案:
-
設置配置項
allowTaint: false
canvas 的 CanvasRenderingContext2D 屬于瀏覽器的對象,如果渲染過跨域資源,瀏覽器就認定 canvas 已經被污染了
Taint
:污點 -
設置配置項
useCORS: false
表示允許跨域資源共享,注意不能與 allowTaint 同時配置為 true
-
img 標簽中添加
crossOrigin = "anonymous"
anonymous:如果使用這個值的話就會在請求 header 中帶上 Origin 屬性,但請求不會帶上 cookie 和客戶端 ssl 證書等其他的一些認證信息
-
圖片服務器配置
Access-Control-Allow-Origin: *
重要的配置項,是跨域問題的根本源泉,需要后端配合
2、截圖鋸齒
解決方案:根據設備像素比進行縮放
// 設置放大倍數
const scale = window.devicePixelRatio;
4、對 css3 支持不好
html2canvas 暫不支持的 CSS 樣式屬性:
background-blend-mode、background-clip: text、box-decoration-break、repeating-linear-gradient()、font-variant-ligatures、mix-blend-mode、writing-mode、writing-mode、border-image、box-shadow、filter、zoom、transform
解決方案:
對于一些必要的樣式,可以選擇使用圖片做兜底實現
box-shadow 可以參考 這個pr,修改源碼解決,但是,實際效果也不是太理想……
5、svg 標簽
問題原因:vue-lottie 動畫庫渲染的標簽是 svg(也可能是你自己寫的 svg 標簽)
html2canvas 對于 svg 標簽的支持也不盡人意,解決辦法同樣是用圖片做兜底
在項目中,我們是用 svg 做動畫,截圖的時候把動畫換成一張靜態圖,這樣只要設置要靜態圖的樣式,截圖效果還是可以接受的
想……
5、svg 標簽
問題原因:vue-lottie 動畫庫渲染的標簽是 svg(也可能是你自己寫的 svg 標簽)
html2canvas 對于 svg 標簽的支持也不盡人意,解決辦法同樣是用圖片做兜底
在項目中,我們是用 svg 做動畫,截圖的時候把動畫換成一張靜態圖,這樣只要設置要靜態圖的樣式,截圖效果還是可以接受的