里講一種實現起來比較簡單的html轉pdf下載的實現。
html2canvas jspdf
通過html2canvas,我們可以將指定的一個dom元素,渲染到canvas中,然后從canva中獲得該圖片,并將圖片通過jspdf來生成。
function createPdf (selector,pagesize,direction,title){
var key = pagesize +''+direction;
var settings = {
'00' : {
pdf : {orientation : 'portrait',format : 'a4',unit : 'px'},
width : 448,
height : 632.5
},
'01' : {
pdf : {orientation : 'landscape',format : 'a4',unit : 'px'},
width : 632.5,
height : 448
},
'10' : {
pdf : {orientation : 'portrait',format : 'a3',unit : 'px'},
width : 632.5,
height : 894.2
},
'11' : {
pdf : {orientation : 'landscape',format : 'a3',unit : 'px'},
width : 894.2,
height : 632.5
}
};
var set = settings[key];
var doc = new jsPDF(set.pdf);
var arr = [];//根據順序保存
var $arr = $(selector);
function tempCreate(){
if($arr.length == 0){//沒有啦
//執行生成
tempPdf();
}else{
var $dom = $arr.splice(0,1);
html2canvas($dom[0]).then(canvas => {
var dataurl = canvas.toDataURL('image/png');
arr.push(dataurl);
tempCreate();
});
}
}
function tempPdf(){
arr.forEach((item,i)=>{
if(i !== 0){
doc.addPage();
}
doc.addImage(item,'png',-1,-1,set.width,set.height);//根據不同的寬高寫入
})
//根據當前的作業名稱
doc.save(title+'.pdf');
}
tempCreate();
}
需要指定容器(依賴jquery),然后指定紙張A4或 A3,以及橫縱向。
//調用
createPdf('.single-page',0,0,'test')
當然,如果是數據量很大的話,就不建議在前臺生成了,最好還是放在后端去做。個人測試過,做A4的圖片生成PDF,當數量大約在100左右的時候,瀏覽器就崩潰了,如果只是幾頁的數據的話,這個方式還是很方便的。
Ps:瀏覽器要是現代瀏覽器哈。
html2canvas : http://html2canvas.hertzen.com/ jspdf :https://github.com/MrRio/jsPDF
avaScript HTML 渲染器
該腳本允許你直接在用戶瀏覽器上對網頁或其中一部分進行“截屏”。截屏是基于DOM的,因此對于真實內容的表示可能不是100%準確的,因為它不是生成實際的截圖,而是基于頁面上可用的信息構建截圖。
工作原理
本腳本通過讀取DOM和應用于元素的不同樣式,將當前頁面渲染為一個canvas(畫布)圖像。
它不需要來自服務器的任何渲染,因為整個圖像是在客戶機的瀏覽器上創建的。但是,由于它過度依賴于瀏覽器,所以這個庫不適合在nodejs中使用。它也不會神奇地繞過任何瀏覽器的內容策略限制,因此在渲染跨域內容時將需要一個代理(https://github.com/niklasvh/html2canvas/wiki/Proxies )j將內容獲取到相同的域(http://en.wikipedia.org/wiki/Same_origin_policy )中。
該腳本目前仍然處于非常實驗性的狀態,所以我不建議在生產環境中使用它,也不建議使用它構建應用程序,因為我們仍然會對它做較大的更改。
瀏覽器兼容性
這個庫在以下瀏覽器中應該會運行良好(帶有Promise polyfill):
由于每個CSS屬性都需要手動構建才能得到支持,因此還有許多屬性尚未得到支持。
用法
本 html2canvas 庫利用了Promise,并期望它們在全局上下文中可用。如果你希望支持目前還不支持本地Promise的舊瀏覽器(http://caniuse.com/#search=promise ),請在包含 html2canvas 庫之前先包含一個polyfill,如es6-promise(https://github.com/jakearchibald/es6-promise )。
要使用html2canvas渲染一個element,只需調用:html2canvas(element[, options]);
該函數會返回一個包含<canvas>元素的Promise(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise )。只需使用then向該Promise添加一個promise執行處理器即可:
構建
你也可以在這里下載已構建好的版本。(https://github.com/niklasvh/html2canvas/releases )
克隆 git源:
安裝依賴:
構建瀏覽器包:
示例
獲取更多信息和示例,請訪問主頁(https://html2canvas.hertzen.com/ )或嘗試test console(測試控制臺 https://html2canvas.hertzen.com/tests/ )。
貢獻
如果你想對本項目貢獻代碼,請將推送請求發送至開發版分支。在提交任何更改之前,請在所有支持的瀏覽器上試運行并測試這些更改。如果一些CSS屬性不被支持或顯示不完整,在提交任何代碼之前,請對這些CSS屬性創建合適的運行環境進行測試。
英文原文:https://github.com/niklasvh/html2canvas 譯者:浣熊君( ????? )
條APP上有個截圖分享功能,就是把文章轉成一張圖片,然后分享到各渠道中去,如微信、QQ等,非常實用,因此,打算就這項功能自己封裝為一個組件ImageGenerator,后期專門進行圖片生成,html是其中的一個源。
頭條截圖分享的實際效果圖
目前前端使用較多的html轉圖片的工具是Html2Canvas,考慮技術儲備和問題討論的充裕性,決定封裝一下這個工具。步驟如下:
按照官方要求,做安裝操作:
npm
npm install html2canvas
我當時下載的是1.4.1的版本。
這個工具有自身的一些限制,使用時要注意:
[1] 并非真正的截圖軟件,而是根據DOM繪制出來的,其繪制能力,完全依賴于工具對DOM和對應屬性的支持和理解;
[2] 因為使用了Canvas支持,生成圖片的區域不能再有Canvas應用,否則會干擾工具的生成,不能保證生成預期,因此,如果使用了Canvas圖表的應用這個工具不推薦使用
這個很簡單,這里就是封裝一個組件,用于后期引入html之外的源生成圖片,同時也做一下圖片的統一顯示,從而和系統整體的設計進行配合。大致的實現思路如下:
上圖,我們引入了工具本身,并設置的結果的顯示區。生成的結果將以節點的方式注入 #image-box 中。
上圖,封裝了一個方法,用途是利用Html2Canvas工具獲得圖片,這里我們引入了一個組件的數據imageData用以存儲和干預生成結果。在這里,我把ImageGenerator封裝為全局組件。
我們在文章的尾部加入一個share功能,點擊彈出分享設置的彈窗,實際效果如下圖所示:
以上技術實現比較簡單,這里就不進行贅述了。上圖中,我們設置了一個生成圖像按鈕,點擊該按鈕則可以觸發我們組件中的對應操作。關鍵思路包括:
【1】這里設置了一個封裝組件shareHandler,封裝了前導模塊和imageGenerator,這兩個模塊的顯示通過一個開關進行控制,該開關則通過圖像生成成功事件進行賦值,這樣的話,我們可以實現圖片生成后,不再顯示前導模塊,而是顯示圖片結果,即ImageGenerator。
【2】這里有一個比較關鍵的操作是shareHandler通過觸發事件將轉換器發射到文章轉換現場,為什么用事件,還是那句話,事件對于解耦和消除組件依賴是最自然的實現。注意,這里我把imageGenerator通過引用的方式作為參數傳出了,這樣的好處是事件將轉換器代入了轉換現場,并可以攜帶回現場轉換結果。
【3】在文章查看器,solutionViewer中,自然會訂閱事件、事件處理和取消訂閱。注意這里的事件處理,實際上是調用了轉換器中我們封裝的函數,參數則是現場取得的,這里的機制很簡單,定義要轉換div的id,作為參數傳入函數。
那么,點擊圖像后,我們可以看到效果圖:
點擊右鍵另存圖像,我們可以獲得一張png格式的圖片,至于后續對下載和到粘貼板的支持,大家可以自行研究和實現。
實現過程中有幾個注意事項:
【1】Canvas返回時,其長寬都是按照實際大小生成的,而我們的例子中,則要根據右抽屜式的彈窗做width=100%,height=auto的處理,這個要如何實現,就是要通過我們在imageGenerator中引入的imageData。
【2】我們的文章顯示中,引入了文件管理的微服務,因此,文章中圖片的鏈接都是跨域的,所以,必須打開html2Canvas的跨域選項,在封裝的組件里,我是通過一共一個defaultOptions來實現這一點的。
這個選項可以在轉換場景提供,也可提供一系列的默認值,最常用的除跨域外,還有是否允許log輸出等開關,大家感興趣可以自行查閱html2Canvas的官網。
內容比較簡單,大家如果有這個應用場景,可以參考實現一下,有問題歡迎大家隨時交流。謝謝大家的支持。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。