HTML頁面轉(zhuǎn)PDF加水印解決截取不全問題

項目需求:根據(jù)HTML頁面導(dǎo)出完整的PDF

技術(shù)棧: html2canvas 、 jspdf 灶壶、 Vue

首先將包下載到項目中蒜焊,然后在制定頁面引入依賴包


import html2Canvas from "html2canvas";

import JsPDF from "jspdf";

定義一個ID為pdfDom的HTML節(jié)點,也就是你想導(dǎo)出的那部分


<div class="right" id="pdfDom">這是PDF的內(nèi)容<div>
<img src="" alt="" v-show="false" id="waterMarkImg">      //  圖片水印的dom元素

首先頁面會被轉(zhuǎn)化為canvas灸异,然后生成圖片后導(dǎo)出PDF文件猜拾,那生成canvas的時候會出現(xiàn)不清晰的問題即舌,那就將canvas的畫布增大兩倍,然后在轉(zhuǎn)成PDF的時候再縮小挎袜,清晰度就會變高顽聂。

接下來在導(dǎo)出按鈕上綁定事件,在點擊事件里粘貼如下代碼

let title = this.articleInfo.title;       // 設(shè)置導(dǎo)出PDF的文件名

var element = document.getElementById("pdfDom");      // 獲取需要導(dǎo)出的DOM節(jié)點

var shareContent = element; //需要截圖的包裹的(原生的)DOM 對象

var width = shareContent.offsetWidth; //獲取dom 寬度

var height = shareContent.offsetHeight; //獲取dom 高度

var canvas = document.createElement("canvas"); //創(chuàng)建一個canvas節(jié)點

var scale = 2; //定義任意放大倍數(shù) 支持小數(shù)

canvas.width = width * scale;

canvas.height = height * scale;

canvas.getContext("2d").scale(scale, scale); //獲取context,設(shè)置scale

var opts = {

       scale: scale, // 添加的scale 參數(shù)

       canvas, //自定義 canvas

       logging: true, //日志開關(guān)盯仪,便于查看html2canvas的內(nèi)部執(zhí)行流程

       width: width, //dom 原始寬度

       height: height,

       useCORS: true // 【重要】開啟跨域配置

};

//     以上部分都是為了強化清晰度的紊搪,放大canvas畫布

html2Canvas(shareContent, opts).then(function(canvas) {
  //  獲取水印元素 
  var img = document.getElementById('waterMarkImg');
  
  var pdf = new JsPDF("p", "mm", "a4"); //A4紙,縱向

  var ctx = canvas.getContext("2d"),

  a4w = 190,

  a4h = 277,      //A4大小全景,210mm x 297mm耀石,四邊各保留10mm的邊距,顯示區(qū)域190x277

  imgHeight = Math.floor((a4h * canvas.width) / a4w), //按A4顯示比例換算一頁圖像的像素高度

  renderedHeight = 0;

  // 【重要】關(guān)閉抗鋸齒   這部分也是為了強化清晰度

  ctx.mozImageSmoothingEnabled = false;

  ctx.webkitImageSmoothingEnabled = false;

  ctx.msImageSmoothingEnabled = false;

  ctx.imageSmoothingEnabled = false;

  while (renderedHeight < canvas.height) {

     var page = document.createElement("canvas");
     // 生成canvas上下文
     let pageCtx = page.getContext("2d");  

     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);
     
     // 在畫布上畫圖
     pageCtx.drawImage(img, 280,1400,2000,800); 
    
     --------------------------------------   華麗的分割線--這里很重要娶牌,是個重要的提醒   -----------------------
     在本地測試的時候是沒有問題的,但是如果上線打包后水印的圖片會替換成線上的地址馆纳,那么問題來了诗良,canvas會有一個圖片跨域的問題。鲁驶。鉴裹。。钥弯。径荔。下面有解決辦法
    
     //添加圖像到頁面,保留10mm邊距脆霎,保留邊距就不會出現(xiàn)文件內(nèi)容在中間被分割的問題

     pdf.addImage(page.toDataURL("image/jpeg", 1.0), "JPEG",10, 10, a4w, Math.min(a4h, (a4w * page.height) / page.width)); 

     renderedHeight += imgHeight;

     if (renderedHeight < canvas.height) pdf.addPage(); //如果后面還有內(nèi)容总处,添加一個空頁
  }

  PDF.save(title + ".pdf");

});

兩個坑

一、還有一個很大的問題就是 jspdf 他是不會自己換頁的睛蛛,所以他可能會把字從中間截斷了
在這里插入圖片描述

醬紫了鹦马,很丑不說吧還影響使用啊,那我給土工兩條思路
1忆肾、如果內(nèi)容是固定的荸频,那么你就可以計算好每一頁的高度了,A4紙的高度大概是840px客冈,那你就在差不多的高度的時候留出空白旭从,那就不會存在截斷的問題
2、如果內(nèi)容高度是后臺返回前端循環(huán)出來的场仲,那么內(nèi)容是不固定的和悦,高度也是不固定的,所以又有兩種方式解決

  • 1燎窘、找到需要打印的 var element = document.getElementById("pdfDom"); 然后取到他的 childrenNodes 去循環(huán)判斷每一個元素距離頂部body的高度是不是整數(shù)比摹闽,如果正好是整數(shù)的時候也就是到了換頁的地方,那就直接在這里換頁褐健,剩下的換到下一頁
  • 如果頁面的總高度是840付鹿,那么到換頁的地方是20的倍數(shù),那么把每一行的行高或者說是高度都設(shè)置成20的整數(shù)倍蚜迅,那么在換頁的時候會是正好的元素的高度結(jié)束的位置舵匾。
二、上面提到的canvas圖片跨域的問題谁不,解決方法有三種

1坐梯、img.setAttribute("crossOrigin",'anonymous'); 設(shè)置允許圖片跨域的屬性
原理:因為canvas禁止訪問外鏈接圖片所以才會引起跨域,那就在圖片上設(shè)置允許跨域的屬性告訴canvas刹帕,我就是允許跨域吵血,剩下的你別管谎替,但是這個需要后臺跟著一起配置cors跨域的access
2、一個神奇的方法蹋辅,就是在圖片的URL后面加個時間戳

let url = 'https://www.tupian.png?'+new Data()..getTime();

3钱贯、第三種方法就是百度搜索在線轉(zhuǎn)換base64,然后把你的線上圖片直接轉(zhuǎn)成base64的格式然后 js 設(shè)置到 imgsrc 上就OK了侦另,最簡單也是最low的方法

嘻嘻嘻秩命,我就用的第三種(小聲bb)
因為我轉(zhuǎn)成PDF的時候用第一種不生效,直接就沒有圖片了我也不知道為啥褒傅,如果有知道為什么的一定要評論告訴我弃锐。第二種加時間戳的方法就是避免了緩存,但是因為要畫到PDF上所以只是畫上了黑色的一個框殿托,圖的占位有了霹菊,但是圖沒有出來,如果又有知道為什么的請及時告訴我
效果圖


image

這個是個表情包是我后加的碌尔,不想讓你們看出來我加了什么水印浇辜。

因為放大了canvas會變得清晰但是canvas在每個瀏覽器會限制高度,所以這個頁面在IE上只能導(dǎo)出4頁多一點就會黑屏唾戚,因為IE的高度是八千多柳洋,所以這個方法導(dǎo)出PDF只是適用固定高度的或者是內(nèi)容不多的。還是建議在服務(wù)端導(dǎo)出PDF吧叹坦,沒有那么多的限制

至此熊镣,就可以到處PDF文件了,寫的不好募书,不喜勿噴

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末绪囱,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子莹捡,更是在濱河造成了極大的恐慌鬼吵,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件篮赢,死亡現(xiàn)場離奇詭異齿椅,居然都是意外死亡,警方通過查閱死者的電腦和手機启泣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進店門涣脚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人寥茫,你說我怎么就攤上這事遣蚀。” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵芭梯,是天一觀的道長险耀。 經(jīng)常有香客問我,道長玖喘,這世上最難降的妖魔是什么胰耗? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮芒涡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘卖漫。我一直安慰自己费尽,他們只是感情好,可當我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布羊始。 她就那樣靜靜地躺著旱幼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪突委。 梳的紋絲不亂的頭發(fā)上柏卤,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天,我揣著相機與錄音匀油,去河邊找鬼缘缚。 笑死,一個胖子當著我的面吹牛敌蚜,可吹牛的內(nèi)容都是我干的桥滨。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼弛车,長吁一口氣:“原來是場噩夢啊……” “哼齐媒!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起纷跛,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤喻括,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后贫奠,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體唬血,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年叮阅,在試婚紗的時候發(fā)現(xiàn)自己被綠了刁品。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡浩姥,死狀恐怖挑随,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情勒叠,我是刑警寧澤兜挨,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布膏孟,位于F島的核電站,受9級特大地震影響拌汇,放射性物質(zhì)發(fā)生泄漏柒桑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一噪舀、第九天 我趴在偏房一處隱蔽的房頂上張望魁淳。 院中可真熱鬧,春花似錦与倡、人聲如沸界逛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽息拜。三九已至,卻和暖如春净响,著一層夾襖步出監(jiān)牢的瞬間少欺,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工馋贤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留赞别,地道東北人。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓配乓,卻偏偏與公主長得像氯庆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子扰付,可洞房花燭夜當晚...
    茶點故事閱讀 45,055評論 2 355