使用React+html2canvas + jspdf實現生成pdf文件


1. 安裝插件

先安裝第一個html2canvas插件,作用是實現將html頁面轉換成圖片

安裝命令如下:

npm install --save html2canvas || npm install html2canvas

然后安裝第二個插件jspdf,作用是將圖片轉為pdf

安裝命令如下:

npm install jspdf --save || npm install jspdf

2. 導入html2canvas和jspdf插件到項目中

import html2canvas from 'html2canvas';
import jsPDF from 'jspdf';

3. 定義一個div和需要生成pdf的頁面 (或者給需要到處的頁面元素最外層加id)

<div id="demo">
  <div style={{marginTop:15}}>
    <div>
    	此為到處的pdf文件
    </div>
  </div>
</div>

4. 定義一個觸發生成pdf文件的按鈕

<Button onClick={download}>生成報告</Button>

5. 實現download方法之一

download = () => {
  const element = document.getElementById('demo');  // 這個dom元素是要導出的pdf的div容器
  const w = element.offsetWidth;  // 獲得該容器的寬
	const h = element.offsetHeight;  // 獲得該容器的高
  const offsetTop = element.offsetTop; // 獲得該容器到文檔頂部的距離  
  const offsetLeft = element.offsetLeft; // 獲得該容器到文檔最左的距離
  const canvas = document.creatElement("canvas");
  let abs = 0;
  const win_i = document.body.clientWidth; // 獲得當前可視窗口的寬度(不包含滾動條)
  const win_o = window.innerWidth; // 獲得當前窗口的寬度(包含滾動條)
  if(win_o > win_i){
    abs = (win_o - win_i) / 2; // 獲得滾動條寬度的一半
  }
	canvas.width = w * 2; // 將畫布寬&&高放大兩倍
  canvas.height = h * 2;
  const context = canvas.getContext('2d');
  context.scale(2, 2);
  context.translate(-offsetLeft - abs, -offsetTop);
  // 這里默認橫向沒有滾動條的情況,因為offset.left(),有無滾動條的時候存在差值,因此translate的時候,要把這個差值去掉
  html2canvas(element, {
    allowTaint: true,
    scale: 2 // 提升畫面質量,但是會增加文件大小
  }).then( canvas => {
    const contentWidth = canvas.width;
    const contentHeight = canvas.height;
    // 一頁pdf顯示html頁面生成的canvas高度
    const pageHeight = contentWidth / 592.28 * 841.89;
    // 未生成pdf的html頁面高度
    const leftHeight = contentHeight;
    // 頁面偏移
    const position = 0;
    // a4紙的尺寸[595.28,841.89],html頁面生成的canvas在pdf中圖片的寬高
    const imgWidth = 595.28;
    const imgHeight = 592.28 / contentWidth * contentHeight;
    
    const pageDate = canvas.toDataURL('image/jpeg', 1.0);
    
    const pdf = new jsPDF('', 'pt', 'a4');
    // 有兩個高度需要區分,一個是html頁面的實際高度,和生成pdf的頁面的高度(841.89)
    // 當內容未超過pdf一頁顯示的范圍,無需分頁
    if(leftHeight < pageHeight) {
      pdf.addImage(pageDate,'JPEG', 0, position, imgWidth, imgHeight);
    }else { // 分頁
      while (leftHeight > 0){
          pdf.addImage(pageDate, 'JPEG', 0, position, imgWidth, imgHeight) 
        	leftHeight -= pageHeight;
        	position -= 841.89;
        	// 避免添加空白頁
        	if(leftHeight > 0){
            pdf.addPage()
          }
      }
    }
    
    pdf.save('你的名字.pdf');    
  })
    
}

方法二:

download = () => {
    const element = document.getElementById('demo');
    const imgHeight = element.clientHeight;
    const imgWidth = element.clientWidth;
    const scale = 3;
    html2canvas(element, {
      letterRendering: true,
      allowTaint: true,
      taintTest: false,
      height: imgHeight,
      //  為了使橫向滾動條的內容全部展示,這里必須指定
      width: imgWidth,
      backgroundColor: '#fff',
      scale: scale, // 提升畫面質量,但是會增加文件大小,
      onclone: (element) => {
       const inputs =  element.getElementsByTagName("input")
       let inputList = Array.prototype.slice.call(inputs);
       inputList.map((item)=>{
         if(item.placeholder){
           item.removeAttribute("placeholder")
         }
       })
       let selectHolder = detail.querySelectorAll(".ant-select-selection-placeholder")
       let selectHolderList = Array.prototype.slice.call(selectHolder)
       selectHolderList.map((item)=>{
         item.style.display = "none"
       })
        // detail.getElementById("campaignInfo_targetGroupDescription").removeAttribute("placeholder")
        // onclone logic to resize div
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve()
            },500)
        })
      }
  }).then((canvas) => {
    const pageData = canvas.toDataURL('image/jpeg', 1);
      // 設置pdf的尺寸,pdf要使用pt單位 已知 1pt/1px = 0.75   pt = (px/scale)* 0.75
      // scale為上面的scale 縮放了scale倍, 60為pdf四周留白
      let pdfX = (imgWidth + 60) / scale * 0.75
      let pdfY = (imgHeight + 60) / scale * 0.75  
      let imgX = (imgWidth / scale * 0.75)
      let imgY = (imgHeight / scale * 0.75); //內容圖片這里不需要留白的距離
      // pdfX,pdfY為pdf的大小,imgX,imgY為內容圖片的大小
      let PDF = new jsPDF('', 'pt', [pdfX, pdfY])
      // 7.5 為坐標,讓img在pdf中水平垂直居中,四周留白均勻
      PDF.addImage(pageData, 'JPEG', 7.5, 7.5, imgX, imgY);
      //獲取當前時間戳
      let timestmp = new Date().getTime()
      PDF.save(`cmt_campaign_basic_info_${lib.dataFormat(timestmp)}.pdf`);
      this.campaignDetailStore.pdfLoadingVisible = false
      // this.setState({
      //   pdfimg:pageData
      // })
  }).catch(() => {
    this.campaignDetailStore.pdfLoadingVisible = false
    // this.setState({ exportPDF: false });
  	});
 };


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM