欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

html2canvas+jspdf實(shí)現(xiàn)下載pdf文件并添加水印

 更新時(shí)間:2024年10月29日 09:47:36   作者:嘻嘻哈哈猿人  
這篇文章主要為大家詳細(xì)介紹了如何使用html2canvas + jspdf進(jìn)行下載pdf文件添加水印,以及echarts圖片防止截?cái)嗵幚?有需要的小伙伴可以了解下

背景

一開(kāi)始實(shí)現(xiàn)長(zhǎng)截圖使用 html2canvas 直接搞定, 后來(lái)改成需要下載 pdf 文件, ... 查找相關(guān)內(nèi)容通過(guò)改造最終全部完成實(shí)現(xiàn)

  • 前端實(shí)現(xiàn)pdf下
  • echarts不能截?cái)?/li>
  • 下載后的內(nèi)容添加水印

jsPdf文檔

html部分

// 使用class 或者 ref 獲取都可以
<div class="pdfDom" ref="pdfDom"> 
   <div data-content-group="content-group" > 不能被截?cái)嗟膬?nèi)容 </div>
    <div data-content-item="content-item"> 不能被截?cái)嗟膬?nèi)容 </div>
    <div data-content-item="content-item"> 不能被截?cái)嗟膬?nèi)容 </div>
    <div data-content-item="content-item"> 不能被截?cái)嗟膬?nèi)容 </div>
    <div data-content-group="content-group">
        <div data-content-item="content-item"> 嵌套的內(nèi)容不能被截?cái)?</div>
        <div data-content-item="content-item"> 嵌套的內(nèi)容不能被截?cái)?</div>
        <div data-content-item="content-item"> 嵌套的內(nèi)容不能被截?cái)?</div>
    </div>
</div>

js部分

import JsPdf from "jspdf";
import html2Canvas from "html2canvas";
import "./simhei-normal.js" // 解決pdf添加水印中文字體亂碼問(wèn)題 ttf轉(zhuǎn)為js后引用

// 這里使用pdf添加水印
function addWatermark (pdf, watermarkText) {
  // 獲取PDF頁(yè)數(shù),給PDF每一頁(yè)添加水印
   var totalPages = pdf.internal.getNumberOfPages();
   for (let i = 1; i <= totalPages; i++) {
     pdf.setPage(i);
     addWatermarkFill(pdf, watermarkText);
   }
   return pdf;
}
function addWatermarkFill (pdf, watermarkText) {
 let pdfW = pdf.internal.pageSize.getWidth();
 let pdfH = pdf.internal.pageSize.getHeight();
 // 250是可以根據(jù)水印的大小調(diào)整的 可以優(yōu)化為單水印的長(zhǎng)和寬
 let xCount = pdfW / 250; 
 let yCount = pdfH / 250;
 // 下面的for循環(huán)的作用是在頁(yè)面上鋪滿水印
 for (let y = 0; y < yCount; y++) {
   let yLocation = y * 250;
   for (let x = 0; x < xCount; x++) {
     let xLocation = x * 250;
     pdf.saveGraphicsState() // 保存圖形狀態(tài)
     pdf.setFontSize(18);       // 設(shè)置水印字體大小
     pdf.setTextColor(200);    // 設(shè)置水印顏色
    //  https://artskydj.github.io/jsPDF/docs/jsPDF.html#setTextColor
     pdf.setGState(pdf.GState({ opacity: 0.3 })) // 設(shè)置透明度為0.3
     // 這里的SIMHEI是字體包 解決jsPDF 無(wú)法使用中文問(wèn)題
    //  pdf.setFont('Alternate-normal');
     pdf.setFont('SIMHEI');
    //  https://artskydj.github.io/jsPDF/docs/jsPDF.html#setFont
     pdf.text(watermarkText, xLocation, yLocation, { align: 'left', angle: -45});
     pdf.restoreGraphicsState()
   }
 }
 return pdf;
}
// 以上代碼為添加水印邏輯處理
// pdfDom 頁(yè)面dom , intervalHeight 留白間距  fileName 文件名 watermarkText: 水印內(nèi)容
export function html2Pdf (pdfDom, intervalHeight, fileName, watermarkText) {
  // 獲取元素的高度
  function getElementHeight (element) {
    return element.offsetHeight;
  }
  // A4 紙寬高
  const A4_WIDTH = 592.28; const A4_HEIGHT = 841.89;
  // 獲取元素去除滾動(dòng)條的高度
  const domScrollHeight = pdfDom.scrollHeight;
  const domScrollWidth = pdfDom.scrollWidth;
  // 保存當(dāng)前頁(yè)的已使用高度
  let currentPageHeight = 0;
  // 獲取所有的元素  我這兒是手動(dòng)給頁(yè)面添加class 用于計(jì)算高度 你也可以動(dòng)態(tài)添加 這個(gè)不重要,主要是看邏輯
  // let elements = pdfDom.querySelectorAll('.content-item'); // 沒(méi)有嵌套邏輯可以直接獲取
  // 代表不可被分頁(yè)的
  const newPage = "content-item"; 
  const wholeNodes = []; // 嵌套元素遍歷出來(lái) push
  // traversingNodes 當(dāng)不可截?cái)嘣剡^(guò)大時(shí)候 遞歸獲取子元素 
  function traversingNodes (nodes) {
    if (nodes.length === 0) return;
    nodes.forEach(element => {
      if (element.nodeType !== 1) return;
      // contentItem 不能截?cái)鄻?biāo)識(shí)
      // contentGroup 嵌套的父級(jí)標(biāo)識(shí)
      const { contentItem: item, contentGroup: group } = element.dataset;
      if (item) {
        const elementHeight = getElementHeight(element);
        console.log(elementHeight, "我是頁(yè)面上的elementHeight"); // 檢查
        // 檢查添加這個(gè)元素后的總高度是否超過(guò) A4 紙的高度
        if (currentPageHeight + elementHeight > A4_HEIGHT) {
        // 如果超過(guò)了,創(chuàng)建一個(gè)新的頁(yè)面,并將這個(gè)元素添加到新的頁(yè)面上
          currentPageHeight = elementHeight;
          element.classList.add(newPage);
          console.log(element, "我是相加高度大于A4紙的元素");
        }
        currentPageHeight += elementHeight;
        wholeNodes.push(element); // 不可截?cái)嘣卮嬖谇短?
      } else if (group) {
        traversingNodes(element.childNodes);
      }
    });
  }
  traversingNodes(pdfDom.childNodes);
  // 遍歷所有內(nèi)容的高度
  // 根據(jù) A4 的寬高等比計(jì)算 dom 頁(yè)面對(duì)應(yīng)的高度

  const pageWidth = pdfDom.offsetWidth;
  const pageHeight = (pageWidth / A4_WIDTH) * A4_HEIGHT;
  // 將所有不允許被截?cái)嗟淖釉剡M(jìn)行處理 如果沒(méi)有嵌套邏輯可以直接獲取 有嵌套邏輯 通過(guò) traversingNodes 遍歷push
  // const wholeNodes = pdfDom.querySelectorAll(`.${newPage}`);
  console.log(wholeNodes, "將所有不允許被截?cái)嗟淖釉剡M(jìn)行處理");
  // 插入空白塊的總高度
  let allEmptyNodeHeight = 0;
  for (let i = 0; i < wholeNodes.length; i++) {
    // 判斷當(dāng)前的不可分頁(yè)元素是否在兩頁(yè)顯示
    const topPageNum = Math.ceil(wholeNodes[i].offsetTop / pageHeight);
    const bottomPageNum = Math.ceil((wholeNodes[i].offsetTop + wholeNodes[i].offsetHeight) / pageHeight);

    // 是否被截?cái)?
    if (topPageNum !== bottomPageNum) {
      // 創(chuàng)建間距
      const newBlock = document.createElement("div");
      newBlock.className = "empty-node";
      newBlock.style.background = "#FFFFFF";

      // 計(jì)算空白塊的高度,可以適當(dāng)留出空間,根據(jù)自己需求而定
      const _H = topPageNum * pageHeight - wholeNodes[i].offsetTop;
      newBlock.style.height = _H + intervalHeight + "px";

      // 插入空白塊
      wholeNodes[i].parentNode.insertBefore(newBlock, wholeNodes[i]);

      // 更新插入空白塊的總高度
      allEmptyNodeHeight = allEmptyNodeHeight + _H + intervalHeight;
    }
  }
  // 這里可以不加 頁(yè)面高度會(huì)變
  //  pdfDom.setAttribute(
  //   'style',
  //   `height: ${domScrollHeight + allEmptyNodeHeight}px; width: ${domScrollWidth}px;`,
  //   )

  return html2Canvas(pdfDom, {
    width: pdfDom.offsetWidth,
    height: pdfDom.offsetHeight,
    useCORS: true,
    allowTaint: true
    // scale: 1
  }).then(canvas => {
    // dom 已經(jīng)轉(zhuǎn)換為 canvas 對(duì)象,可以將插入的空白塊刪除了
    const emptyNodes = pdfDom.querySelectorAll(".empty-node");
    for (let i = 0; i < emptyNodes.length; i++) {
      emptyNodes[i].style.height = 0;
      emptyNodes[i].parentNode.removeChild(emptyNodes[i]);
    }
    
    const canvasWidth = canvas.width; const canvasHeight = canvas.height;
    // html 頁(yè)面實(shí)際高度
    let htmlHeight = canvasHeight;
    // 頁(yè)面偏移量
    let position = 0;
   
    // 根據(jù) A4 的寬高等比計(jì)算 pdf 頁(yè)面對(duì)應(yīng)的高度
    const pageHeight = (canvasWidth / A4_WIDTH) * A4_HEIGHT;
   
    // html 頁(yè)面生成的 canvas 在 pdf 中圖片的寬高
    const imgWidth = A4_WIDTH;
    const imgHeight = 592.28 / canvasWidth * canvasHeight;
    // 將圖片轉(zhuǎn)為 base64 格式
    const imageData = canvas.toDataURL("image/jpeg", 1.0);
    
    
    // 生成 pdf 實(shí)例
    let PDF = new JsPdf("", "pt", "a4", true); 
    // html 頁(yè)面的實(shí)際高度小于生成 pdf 的頁(yè)面高度時(shí),即內(nèi)容未超過(guò) pdf 一頁(yè)顯示的范圍,無(wú)需分頁(yè)
    if (htmlHeight <= pageHeight) {
      PDF.addImage(imageData, "JPEG", 0, 0, imgWidth, imgHeight);
    } else {
      while (htmlHeight > 0) {
        PDF.addImage(imageData, "JPEG", 0, position, imgWidth, imgHeight);
        // 更新高度與偏移量
        htmlHeight -= pageHeight;
        position -= A4_HEIGHT;
        if (htmlHeight > 0) {
          // 在 PDF 文檔中添加新頁(yè)面
          PDF.addPage();
        }
      }
    }
    PDF = addWatermark(PDF, watermarkText );
    // 保存 pdf 文件
    PDF.save(`${fileName}.pdf`);
  }).catch(err => {
    console.log(err);
  });
}

調(diào)用

    import { html2Pdf } from "./outpdf.js";

    const pdfDom = ref();
    html2Pdf(pdfDom.value, 20, "下載PDF文件", "水印文字");

水印添加問(wèn)題

添加水印的時(shí)候遇到了中文亂碼問(wèn)題 查看文檔jspdf 是支持自定義字體的

在電腦中找到找到font文件 也可以在網(wǎng)上下載對(duì)應(yīng)的 ttf 文件 我這里用的 黑體常規(guī)

ttf文件轉(zhuǎn)換為 js 文件 ttf文件轉(zhuǎn)js地址jsPdf文檔首頁(yè)中有講到Use of UTF-8 / TTF:

將轉(zhuǎn)換后的js文件,導(dǎo)入到工程內(nèi)用,在文件內(nèi)引入,用jsPDF里的 setFont()方法加載一下字體包

到此這篇關(guān)于html2canvas+jspdf實(shí)現(xiàn)下載pdf文件并添加水印的文章就介紹到這了,更多相關(guān)html2canvas jspdf下載pdf內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論