把網(wǎng)頁下載為圖片或打印成PDF

最近遇到了需要把網(wǎng)頁下載為圖片和打印為PDF的需求坚芜,特此整理凶掰。

一吴汪、借助瀏覽器

一般瀏覽器都自帶PDF打印功能:

至于保存為圖片钞楼,有很多瀏覽器插件(比如screenshot沽翔、花瓣)等,都可以將網(wǎng)頁保存為圖片窿凤。

缺點:

  1. 網(wǎng)頁中的圖標(biāo)仅偎、背景等可能無法打印成PDF,因此效果不好雳殊;
  2. 很多時候我們想打印網(wǎng)頁的某一部分(而不是整個網(wǎng)頁)橘沥,因此可定制性較差。

因此我們需要結(jié)合js來實現(xiàn)以上需求夯秃。

二座咆、用js

1、js + 瀏覽器打印功能

(1)打印整個頁面:

window.print()

(2)打印頁面中的指定元素:
一般來說仓洼,我們會用CSS將不需要打印的元素隱藏掉介陶,這樣body中實際上就只剩我們希望打印的頁面部分:

@media print {
    body * {
        visibility: hidden;
    }
    #printArea, #printArea * {
        visibility: visible;
    }
    #printArea {
        position: fixed;
        left: 0;
        top: 0;
        right:0;
        bottom:0;
    }
}

再調(diào)用window.print()即可。

但是測試后發(fā)現(xiàn)色建,這種方法還是存在問題:如果要打印的元素較長(大于一屏)哺呜,大于一屏的部分不會被打印。

我們再換一種思路:

//打印區(qū)域的內(nèi)容
var printContents = document.getElementById('printArea').innerHTML
//頁面的所有內(nèi)容
var originalContents = document.body.innerHTML
        
document.body.innerHTML = printContents
window.print()
document.body.innerHTML = originalContents
//直接恢復(fù)頁面可能會造成頁面“假死”箕戳,可通過重新加載的方式恢復(fù)
window.location.reload()

打印的時候?qū)⒁蛴〉牟糠衷O(shè)置為當(dāng)前頁面的全部內(nèi)容某残,打印完之后又將頁面恢復(fù)。

分別打印一個頁面上的多個區(qū)域:

//第一個打印區(qū)域的內(nèi)容
var printContents1 = document.getElementById('printArea1').innerHTML
//第二個打印區(qū)域的的內(nèi)容
var printContents2 = document.getElementById('printArea2').innerHTML
//頁面的所有內(nèi)容
var originalContents = document.body.innerHTML

//打印第一個區(qū)域
document.body.innerHTML = printContents1
window.print()
//打印第二個區(qū)域
document.body.innerHTML = printContents2
window.print()
//恢復(fù)頁面
document.body.innerHTML = originalContents
//直接恢復(fù)頁面可能會造成頁面“假死”陵吸,可通過重新加載的方式恢復(fù)
window.location.reload()

這種方法可以使得每次打印時要打印的內(nèi)容都在頁面開頭玻墅,并且對于超過一屏的打印也正確。

存在的問題:
打印完之后需手動將頁面恢復(fù)至原來的html結(jié)構(gòu)壮虫,恢復(fù)之后發(fā)現(xiàn)頁面“假死”澳厢,無法再進(jìn)行其他交互,因此我調(diào)用了window.location.reload()將頁面刷新囚似。但是這樣做實際上是沒有保存頁面目前的一些數(shù)據(jù)和交互信息剩拢,因此用戶體驗也不好。

如果不希望犧牲用戶體驗谆构,可以將要打印的內(nèi)容寫入新的瀏覽器窗口并打開裸扶,打印完之后關(guān)閉該新窗口:

var printContents = document.getElementById('printArea').innerHTML
//打開打印窗口
var newWin = window.open()
newWin.document.write(printContents)
newWin.print()
//關(guān)閉打印窗口
newWin.close()

我們會發(fā)現(xiàn)框都,使用這種方法的話搬素,打印內(nèi)容的css樣式實際上是失效的呵晨,因為在打印窗口頁面并沒有引入相關(guān)的css,所以我們需要手動引入:

var printContents = document.getElementById('printArea').innerHTML
var newWin = window.open()
//引入css
var printCommonStyle=`
    <style>
        *{
            box-sizing: border-box;
        }
        .text-center{
            text-align: center;
        }
        
        a,a:link,a:visited,a:hover,a:active{
            color: #000;
            text-decoration: none;
        }
        
        /*設(shè)置打印時的table樣式*/
        table{
            border-spacing: 0px;
            border-bottom: 1px solid;
        }
        th,td {
            padding: 4px 4px;
            word-break: break-all;
            border-top: 1px solid;
            border-left: 1px solid;
        }
        tr>th:last-child,
        tr>td:last-child {
            border-right: 1px solid;
        }
    </style>
`
newWin.document.write( printCommonStyle+printContents )
newWin.print()
newWin.close()

這樣也能實現(xiàn)一些場景下的打印要求(比如表格熬尺、文字等)摸屠。

2、js插件實現(xiàn)打印功能

下載為圖片:html2canvas + a標(biāo)簽download屬性
打印為PDF:html2canvas + jsPDF

首先我們看看這幾個js的使用方法:

1)html2canvas

步驟:引入html2canvas.js粱哼,在Promise.then中獲取轉(zhuǎn)換好的canvas:

//通過html2canvas把html渲染成canvas季二,然后獲取圖片數(shù)據(jù)
html2canvas(document.getElementById('showPart')).then(function(canvas) {            
     //將canvas轉(zhuǎn)成PDF或者下載圖片
    //.........................................
});
2)下載圖片

其實要用到a標(biāo)簽的download特性:

//通過html2canvas把html渲染成canvas,然后獲取圖片數(shù)據(jù)
html2canvas(document.getElementById('showPart')).then(function(canvas) {
    //下載圖片
    var aElement=document.createElement('a');
    aElement.setAttribute('href',imageData);    //重點看這里
    aElement.setAttribute('download','test.png');    //重點看這里
    document.body.insertAdjacentElement('beforeend',aElement)
    aElement.click();
});
3)jsPDF

(1)文字打印成PDF:

var doc=new jsPDF()
doc.text('hello world!',10,10)
 doc.save('a4.pdf')

(2)圖片打印成PDF:

我們看看官網(wǎng)的例子:

注意:jsPDF需要的是data URL的圖片格式揭措。

借助于官網(wǎng)的例子胯舷,我們進(jìn)行一下模擬,代碼:

var imageData='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QA/wD/AP+gvaeTAAAAB3RJTUUH3gwKEAonDW4kCwAAAodJREFUaN7t2LtrFUEYxuFHTWGCBrzFS6WilcGgnSAoGLX2UgiChSGF2NtYiEII+C8E0oid0VqxUBDsFAUrRS0UUYkBlaNgvBQzMcclObvubLIp9q12l/lm3t/M7M73LY0aNWpUp5ZV2dnmC08LtXt3dffSA8iYX4F16I33nzGJn1VDJANkjPdgEMcxgLXx+Sc8wU3cRasqkCSAjPmtuIyTEWQutXADl/C6CoiuJPxZbcMYDuW068EZbMFwO0RZLS8b2Db7PcLM55lv1yCuxNjCL3+lABkzJ0rEnYixSUoF6NJ5z3dST4xN2sapAGuEr01ZDcQ+agNYm2hgjdlPbS0AVRyESX2kAkxiKiF+KvZRG8AUHifEP06cgGSAaSE9aJWIbcXY6ToBCLnNRIm4iRibpKpyoe0Yx4GCofdxFi9Jy4WqWAHRyBCu6bydWrHN0Iz5VC1UOn0Me82eEVN4hFuWUjo9DwSzBc3KeP9dpqCpwnxlADkw/6jKcrIygA3D90rFfRw7WA9AB8PLhG3TjdVYFZ9/xRd8E7bT76qA/gtgHuN92ClklruwAxuj+fZ34Cve4wWeCTXyc3xIASkEMIfxddiHo9gvlJS9/zEhv4U/Fa/wALfxUCYvKgKSO2DGfJ9QhJzGHmGrVKFvQl50XSj6/65KHkRHgIz5I7gozHhVB2BWv4QVGcGdIhDzArSZXy4c+yPCCiyGPsTJGo9Q80IUmcmjGF1E8+JYozic1zAPoBvnsH4Rzc9oPc7Lec/yADahvwbzM+qPHkoDdKnu710Z5Y6/UF+TRVMRgDohc8fO2x7TeBuvf9Vg/q2cmjkP4A1OFWi3UJqOHkoD/BDylUaNGjVqNKf+AN+rkUhAKMRGAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTExLTEyVDExOjAyOjI0KzA4OjAwmpHX/gAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNC0xMi0xMFQxNjoxMDozOSswODowMOM3CTMAAABNdEVYdHNvZnR3YXJlAEltYWdlTWFnaWNrIDcuMC4xLTYgUTE2IHg4Nl82NCAyMDE2LTA5LTE3IGh0dHA6Ly93d3cuaW1hZ2VtYWdpY2sub3Jn3dmlTgAAABh0RVh0VGh1bWI6OkRvY3VtZW50OjpQYWdlcwAxp/+7LwAAABh0RVh0VGh1bWI6OkltYWdlOjpIZWlnaHQAMTI4Q3xBgAAAABd0RVh0VGh1bWI6OkltYWdlOjpXaWR0aAAxMjjQjRHdAAAAGXRFWHRUaHVtYjo6TWltZXR5cGUAaW1hZ2UvcG5nP7JWTgAAABd0RVh0VGh1bWI6Ok1UaW1lADE0MTgxOTkwMzk6CQwlAAAAEnRFWHRUaHVtYjo6U2l6ZQAxLjA3S0Lad01iAAAAX3RFWHRUaHVtYjo6VVJJAGZpbGU6Ly8vaG9tZS93d3dyb290L3NpdGUvd3d3LmVhc3lpY29uLm5ldC9jZG4taW1nLmVhc3lpY29uLmNuL3NyYy8xMTgyMS8xMTgyMTEyLnBuZ9ePzJoAAAAASUVORK5CYII='
var doc = new jsPDF()
doc.addImage(imageData,'png',0,0,100,100)
doc.save('resume.pdf')
4)得到data url

其實這個功能只是調(diào)用一個toDataURL的API而已绊含,所以不需要用什么插件桑嘶,直接調(diào)用就可以了:

//默認(rèn)的轉(zhuǎn)換類型:"image/png"
var imageData=canvas.toDataURL()

知道上述幾個API和插件的基本用法后,我們來將它們組合起來:先使用html2canvas把網(wǎng)頁轉(zhuǎn)成canvas躬充,再使用toDataURL()方法把canvas轉(zhuǎn)成data url逃顶,最后用jsPDF把data url轉(zhuǎn)成PDF,簡直完美充甚!

完整代碼如下:

html2canvas(document.getElementById('showPart')).then(function(canvas) {
    //通過html2canvas把html渲染成canvas
    document.body.appendChild(canvas);
            
    //canvas轉(zhuǎn)成dataurl
    var imageData=canvas.toDataURL()
            
    //dataurl轉(zhuǎn)成PDF          
    var doc = new jsPDF('','pt','a4')
    doc.addImage(imageData,'png', 0, 0, 595, 595/canvas.width * canvas.height)  //使圖片占滿整張A4紙
    doc.save('test.pdf')
});

------補(bǔ)充-------

測試發(fā)現(xiàn)以政,以上代碼得到的結(jié)果存在兩個嚴(yán)重問題:

  1. 當(dāng)圖片比較長時,超出A4紙長度的那部分圖片會被截掉
  2. 最終得到的PDF不清晰伴找,很模糊

我翻看了很多資料盈蛮,試了很多方法,分頁解決了技矮,但是得到的PDF還是很模糊眉反。目前還未解決,先在這里占個坑吧穆役,等到解決了再來整理寸五。

總之,目前還沒找到完美的方案來解決打印的問題耿币,如果您有什么解決方案梳杏,可以多多交流哦~~

參考:
1、Print <div id=“printarea”></div> only?
2淹接、Javascript 將html轉(zhuǎn)成pdf,下載,支持多頁哦
3十性、html導(dǎo)出pdf文件
4、問:html5 canvas繪制圖片模糊的問題

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末塑悼,一起剝皮案震驚了整個濱河市劲适,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌厢蒜,老刑警劉巖霞势,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件烹植,死亡現(xiàn)場離奇詭異,居然都是意外死亡愕贡,警方通過查閱死者的電腦和手機(jī)草雕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來固以,“玉大人墩虹,你說我怎么就攤上這事『┝眨” “怎么了诫钓?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長篙螟。 經(jīng)常有香客問我尖坤,道長,這世上最難降的妖魔是什么闲擦? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任慢味,我火速辦了婚禮,結(jié)果婚禮上墅冷,老公的妹妹穿的比我還像新娘纯路。我一直安慰自己,他們只是感情好寞忿,可當(dāng)我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布驰唬。 她就那樣靜靜地躺著,像睡著了一般腔彰。 火紅的嫁衣襯著肌膚如雪叫编。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天霹抛,我揣著相機(jī)與錄音搓逾,去河邊找鬼。 笑死杯拐,一個胖子當(dāng)著我的面吹牛霞篡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播端逼,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼朗兵,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了顶滩?” 一聲冷哼從身側(cè)響起余掖,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎礁鲁,沒想到半個月后盐欺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體赁豆,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年找田,在試婚紗的時候發(fā)現(xiàn)自己被綠了歌憨。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片着憨。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡墩衙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出甲抖,到底是詐尸還是另有隱情漆改,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布准谚,位于F島的核電站挫剑,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏柱衔。R本人自食惡果不足惜樊破,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望唆铐。 院中可真熱鬧哲戚,春花似錦、人聲如沸艾岂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽王浴。三九已至脆炎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間氓辣,已是汗流浹背秒裕。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留钞啸,地道東北人簇爆。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像爽撒,于是被迫代替她去往敵國和親入蛆。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內(nèi)容

  • 用到的組件 1硕勿、通過CocoaPods安裝 2哨毁、第三方類庫安裝 3、第三方服務(wù) 友盟社會化分享組件 友盟用戶反饋 ...
    SunnyLeong閱讀 14,608評論 1 180
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫源武、插件扼褪、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,066評論 4 62
  • 今天一個人去散步想幻,突然發(fā)現(xiàn)自己很孤單,以前一直以來都有很多很多的朋友在身邊话浇,當(dāng)他人約我一起吃飯也好脏毯,散步也好,怎樣...
    高藝菲Sophia閱讀 294評論 2 1
  • 總想把你珍藏 只因你純真模樣 總想留住時光 深情依然 月夜的故事 吐放玫瑰花香 縈繞成繭 你在那里 牽動思念的線 ...
    律墨閱讀 368評論 9 5
  • 姓名:邵逸軒 公司:寧波禾隆新材料股份有限公司 六項精進(jìn)第340期努力一組學(xué)員 【日精進(jìn)打卡第13天】 【知~學(xué)習(xí)...
    邵逸軒閱讀 158評論 0 0