網(wǎng)站開發(fā)技術(shù)的現(xiàn)狀及發(fā)展趨勢今日十大熱點(diǎn)新聞
前端如何生成pdf
開發(fā)背景: 需要給頁面中相應(yīng)的內(nèi)容生成pdf,查找文檔后發(fā)現(xiàn)要用到兩個插件。html2canvas 以及 jsPDF
html2canvas
給dom結(jié)構(gòu)轉(zhuǎn)化為canvas,然后生成各種類型圖片jsPDF
把canvas 生成的圖片url 轉(zhuǎn)化為pdf
// 插入圖片
pdf.addImage(image, format, x, y, width, height, alias, compression, rotation)
// 保存為pdf
pdf.save("example.pdf");
參數(shù)
- image:表示要插入的圖片資源,可以是圖片文件的路徑或者base64編碼字符串。
- format:表示要插入的圖片格式,包括:‘JPEG’, ‘PNG’, ‘GIF’, ‘BMP’, ‘TIFF’, ‘RAW’, ‘JPEG2000’。
- x:圖片在PDF中的x軸坐標(biāo),單位為pt(點(diǎn))。
- y:圖片在PDF中的y軸坐標(biāo),單位為pt(點(diǎn))。
- width:圖片在PDF中的寬度,單位為pt(點(diǎn))。
- height:圖片在PDF中的高度,單位為pt(點(diǎn))。
- alias(可選):指定圖片資源的別名。
- compression(可選):指定圖片的壓縮質(zhì)量,取值為0-1之間的浮點(diǎn)數(shù)。
- rotation(可選):指定圖片的旋轉(zhuǎn)角度,取值范圍為0-360之間的整數(shù)。
下面是dom轉(zhuǎn)化為pdf 的基本代碼
import html2canvas from 'html2canvas';
import jsPdf from 'jspdf';function printPDF () {const domElement = document.getElementById('your-id');html2canvas(domElement, {onclone: (document) => {document.getElementById('print-button').style.visibility = 'hidden';}}).then((canvas) => {const img = canvas.toDataURL('image/png');const pdf = new jsPdf();pdf.addImage(imgData, 'JPEG', 0, 0, width, height);pdf.save('your-filename.pdf');
})
需要特別注意一下 html2canvas onclone
方法。它是當(dāng)DOM被克隆后進(jìn)行渲染時的回調(diào)函數(shù),可用于修改將要渲染的內(nèi)容,而不會影響原始DOM。當(dāng)你需要在生成快照前操作 DOM(例如隱藏打印按鈕)時,會非常有用。
難點(diǎn)突破
1. 使用html2canvas轉(zhuǎn)為圖片遇到跨域問題
跨域圖片不會生成:由于跨域的問題(比如圖片在第三方存放),導(dǎo)致圖片不會被繪制,需要多方配置;
1. html2canvas
的配置項(xiàng)中配置 allowTaint:true
或 useCORS:true
(二者不可共同使用)
2. img標(biāo)簽增加 crossOrigin='anonymous'
3. 圖片服務(wù)器配置Access-Control-Allow-Origin
或使用代理
其中第三步是最重要的,不設(shè)置則前兩步設(shè)置了也無效。
如果后端不能改圖片服務(wù)器,咱們前端也能設(shè)置圖片代理,例如nginx server配置
location /img {proxy_pass 服務(wù)器真正地址;}
2. html2canvas轉(zhuǎn)化的圖片,ios設(shè)備長按可以保存,Android設(shè)備長按無法保存
- 原因分析:轉(zhuǎn)換后使用canvas.toDataURL拿到的是base64的圖片,此圖片可以直接展示在網(wǎng)頁上,但是在Android設(shè)備上長按此圖片無法保存,ios設(shè)備可以長按保存;原因是Android無法長按保存base64的圖片,
- 解決辦法:可以考慮將圖片先上傳到服務(wù)器拿到url再展示
3. safir長按保存不了圖片
使用-webkit-touch-callout:default
不規(guī)范的屬性,iOS 2.0及更高版本的Safari瀏覽器可用
4. 生成的圖片中若包含二維碼,微信長按圖片偶現(xiàn)無法識別
不使用路由切換,使用window.location.href直接跳轉(zhuǎn)刷新頁面
5. 生成的PDF超出一頁后分頁問題
- 需要計(jì)算圖片的寬高,一頁展示多少
看詳細(xì)代碼
printPDF(id, name){const domElement = document.getElementById(id);html2canvas(domElement, {allowTaint: false,useCORS: true, // 用于解決圖片跨域onclone: (document) => {document.getElementById('print-button').style.visibility = 'hidden';}}).then((canvas) => {const fileName = name + (new Date()).toLocaleString() + '.pdf'var pdf = new jsPdf('p', 'mm', 'a4'); // A4紙,縱向var ctx = canvas.getContext('2d');var a4w = 190; var a4h = 277; // A4大小,210mm x 297mm,四邊各保留10mm的邊距,顯示區(qū)域190x277var imgHeight = Math.floor(a4h * canvas.width / a4w); // 按A4顯示比例換算一頁圖像的像素高度var renderedHeight = 0;while (renderedHeight < canvas.height) {var page = document.createElement('canvas');page.width = canvas.width;page.height = Math.min(imgHeight, canvas.height - renderedHeight);// 可能內(nèi)容不足一頁 // 用getImageData剪裁指定區(qū)域,并畫到前面創(chuàng)建的canvas對象中page.getContext('2d').putImageData(ctx.getImageData(0, renderedHeight, canvas.width, Math.min(imgHeight, canvas.height - renderedHeight)), 0, 0);pdf.addImage(page.toDataURL('image/jpeg', 1.0), 'JPEG', 10, 10, a4w, Math.min(a4h, a4w * page.height / page.width)); // 添加圖像到頁面,保留10mm邊距renderedHeight += imgHeight;if (renderedHeight < canvas.height) {pdf.addPage();// 如果后面還有內(nèi)容,添加一個空頁}// delete page;}// 保存文件pdf.save(fileName);})}