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

使用pdf-lib.js實現(xiàn)pdf添加自定義水印功能

 更新時間:2024年11月14日 15:20:38   作者:忠實米線  
pdf-lib是一個強大的JavaScript庫,允許在任何JavaScript環(huán)境中創(chuàng)建和修改PDF文檔,下面就跟隨小編一起來學(xué)習一下如何使用pdf-lib實現(xiàn)pdf添加自定義水印功能吧

項目介紹

pdf-lib是一個強大的JavaScript庫,允許在任何JavaScript環(huán)境中創(chuàng)建和修改PDF文檔。無論是前端瀏覽器環(huán)境還是Node.js服務(wù)器端,它都能提供全面的功能來滿足你的需求。

快速啟動

要開始使用pdf-lib,首先確保你已經(jīng)安裝了相應(yīng)的npm包。在命令行中運行以下命令:

npm install --save pdf-lib

或者如果你是yarn的使用者:

yarn add pdf-lib

實現(xiàn)代碼

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>PDF Watermark Example</title>
  <script src="https://cdn.bootcdn.net/ajax/libs/pdf-lib/1.17.1/pdf-lib.min.js"></script> 
</head>

<body>
  <input type="file" id="pdfFile" accept="application/pdf">
  <button onclick="addWatermark()">添加水印</button>
  <a id="downloadLink" style="display:none;">下載PDF</a>

  <script>
    async function addWatermark() {
      const fileInput = document.getElementById('pdfFile');
      const file = fileInput.files[0];

      if (!file) {
        alert('請選擇一個PDF文件');
        return;
      }

      const arrayBuffer = await file.arrayBuffer();
      const pdfDoc = await PDFLib.PDFDocument.load(arrayBuffer);
      const pages = pdfDoc.getPages();
      // 獲取當前時間并格式化
      const now = new Date();
      const year = now.getFullYear();
      const month = String(now.getMonth() + 1).padStart(2, '0');
      const day = String(now.getDate()).padStart(2, '0');
      const hour = String(now.getHours()).padStart(2, '0');
      const minute = String(now.getMinutes()).padStart(2, '0');

      // 創(chuàng)建水印
      const watermarkText = `無敵暴龍獸-${year}-${month}-${day}-${hour}:${minute}-加密`;
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      const fontSize = 20;
      const textColor = 'rgba(0, 0, 0, 0.2)';

      // 計算文本寬度和高度
      ctx.font = `${fontSize}px Arial`;
      const textMetrics = ctx.measureText(watermarkText);
      const textWidth = textMetrics.width;
      const textHeight = fontSize;

      // 計算旋轉(zhuǎn)后的文本邊界
      const angle = -Math.PI / 4; // 旋轉(zhuǎn)45度
      const rotatedWidth = Math.abs(textWidth * Math.cos(angle)) + Math.abs(textHeight * Math.sin(angle));
      const rotatedHeight = Math.abs(textHeight * Math.cos(angle)) + Math.abs(textWidth * Math.sin(angle));

      // 設(shè)置Canvas大小
      canvas.width = rotatedWidth + 20; // 增加一些邊距
      canvas.height = rotatedHeight + 20;

      // 繪制水印文本
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      ctx.translate(canvas.width / 2, canvas.height / 2);
      ctx.rotate(angle);
      ctx.font = `${fontSize}px Arial`;
      ctx.fillStyle = textColor;
      ctx.textAlign = 'center';
      ctx.textBaseline = 'middle';
      ctx.fillText(watermarkText, 0, 0);

      // 將Canvas轉(zhuǎn)換為Image對象
      const image = new Image();
      image.src = canvas.toDataURL('image/png');

      // 添加水印到每一頁PDF
      for (const page of pages) {
        const { width, height } = page.getSize();

        // 計算新的水印尺寸,以便它可以跨越頁面的兩個相鄰邊緣
        const cornerMargin = 50; // 角落與頁面邊緣之間的最小距離
        const cornerSizeMultiplier = 0.5; // 控制水印相對于頁面尺寸的比例
        const scale = 1; // 水印縮放比例

        const cornerWidth = Math.min(width, height) * cornerSizeMultiplier * scale;
        const cornerHeight = cornerWidth; // 假設(shè)是正方形水印

        // 計算水印的新位置,使其跨越頁面的兩個相鄰邊緣
        const positions = [
          { x: cornerMargin, y: cornerMargin }, // 左上角
          { x: width - cornerWidth - cornerMargin, y: cornerMargin }, // 右上角
          { x: cornerMargin, y: height - cornerHeight - cornerMargin }, // 左下角
          { x: width - cornerWidth - cornerMargin, y: height - cornerHeight - cornerMargin } // 右下角
        ];

        // 需要重新創(chuàng)建水印圖像以匹配新尺寸
        const newCanvas = document.createElement('canvas');
        const newCtx = newCanvas.getContext('2d');
        newCanvas.width = cornerWidth;
        newCanvas.height = cornerHeight;

        // 復(fù)制舊水印到新畫布
        newCtx.drawImage(canvas, 0, 0, cornerWidth, cornerHeight);

        // 將新畫布轉(zhuǎn)換回Image對象
        const newImage = new Image();
        newImage.src = newCanvas.toDataURL('image/png');

        // 嵌入新水印到PDF文檔
        const newImg = await pdfDoc.embedPng(newImage.src);

        for (const pos of positions) {
          page.drawImage(newImg, {
            x: pos.x,
            y: pos.y,
            width: newImg.width,
            height: newImg.height,
          });
        }
      }

      // 保存修改后的PDF
      const pdfDataUri = await pdfDoc.saveAsBase64({ dataUri: true });
      const downloadLink = document.getElementById('downloadLink');
      downloadLink.href = pdfDataUri;
      downloadLink.download = 'watermarked.pdf';
      downloadLink.click();
    }
  </script>
</body>

</html>

效果圖

到此這篇關(guān)于使用pdf-lib.js實現(xiàn)pdf添加自定義水印功能的文章就介紹到這了,更多相關(guān)pdf-lib實現(xiàn)pdf添加自定義水印內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JavaScript常見打開鏈接的幾種方法小結(jié)

    JavaScript常見打開鏈接的幾種方法小結(jié)

    在頁面中的鏈接除了常規(guī)的方式以外,如果使用javascript,還有很多種方式,下面這篇文章主要給大家介紹了關(guān)于JavaScript常見打開鏈接的幾種方法,需要的朋友可以參考下
    2024-01-01
  • assert()函數(shù)用法總結(jié)(推薦)

    assert()函數(shù)用法總結(jié)(推薦)

    assert的作用是現(xiàn)計算表達式 expression ,如果其值為假(即為0),那么它先向stderr打印一條出錯信息,然后通過調(diào)用 abort 來終止程序運行。這篇文章主要介紹了assert()函數(shù)用法總結(jié),需要的的朋友參考下
    2017-01-01
  • 一文解決前端JS小數(shù)運算精度問題

    一文解決前端JS小數(shù)運算精度問題

    在做項目的時候,前端需要在表格的底部做一個匯總的功能,在采用reduce對當前屬性所有值匯總時,發(fā)現(xiàn)匯總結(jié)果存在好長的小數(shù)位,本文給大家介紹了如何解決前端JS小數(shù)運算精度問題,需要的朋友可以參考下
    2024-02-02
  • javascript發(fā)送短信驗證碼實現(xiàn)代碼

    javascript發(fā)送短信驗證碼實現(xiàn)代碼

    我們在注冊賬號,或者是參加活動時,都會向手機發(fā)送收短信驗證碼,短信驗證碼到底是如何實現(xiàn)的,本文為大家揭曉,并為大家分項1javascript發(fā)送短信驗證碼實現(xiàn)代碼,感興趣的小伙伴們可以參考一下
    2015-11-11
  • js中關(guān)于new Object時傳參的一些細節(jié)分析

    js中關(guān)于new Object時傳參的一些細節(jié)分析

    這里討論給Object傳參時,其內(nèi)部的處理。參考:ECMA262 V5 15.2.2.1
    2011-03-03
  • 淺析JS中的 map, filter, some, every, forEach, for in, for of 用法總結(jié)

    淺析JS中的 map, filter, some, every, forEach, for in, for of 用法總

    本文是小編給大家總結(jié)的關(guān)于javascript中的map, filter, some, every, forEach, for in, for of 用法,非常不錯,具有參考借鑒價值,需要的朋友參考下吧
    2017-03-03
  • 基于Bootstrap模態(tài)對話框只加載一次 remote 數(shù)據(jù)的解決方法

    基于Bootstrap模態(tài)對話框只加載一次 remote 數(shù)據(jù)的解決方法

    下面小編就為大家?guī)硪黄贐ootstrap模態(tài)對話框只加載一次 remote 數(shù)據(jù)的解決方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • 微信jssdk踩坑之簽名錯誤invalid signature

    微信jssdk踩坑之簽名錯誤invalid signature

    這篇文章主要介紹了微信jssdk踩坑之簽名錯誤invalid signature,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友們下面隨著小編來一起學(xué)習學(xué)習吧
    2020-05-05
  • JavaScript 隱性類型轉(zhuǎn)換步驟淺析

    JavaScript 隱性類型轉(zhuǎn)換步驟淺析

    隱性類型轉(zhuǎn)換,是==引起的轉(zhuǎn)換,下面通過本文給大家分享JavaScript 隱性類型轉(zhuǎn)換步驟,感興趣的朋友一起看看吧
    2018-03-03
  • Javascript 原型和繼承(Prototypes and Inheritance)

    Javascript 原型和繼承(Prototypes and Inheritance)

    前面我們看到了如何使用 constructor 來初始化對象。如果這樣做,那么每一個創(chuàng)建的新對象都會對那些相同的屬性,方法建立一個獨立的副本。而實際上有更加有效的方法來指定方法,常量,以及其他一些可被所有該類的對象共享的屬性。
    2009-04-04

最新評論