使用pdf-lib.js實(shí)現(xiàn)pdf添加自定義水印功能
項(xiàng)目介紹
pdf-lib是一個(gè)強(qiáng)大的JavaScript庫,允許在任何JavaScript環(huán)境中創(chuàng)建和修改PDF文檔。無論是前端瀏覽器環(huán)境還是Node.js服務(wù)器端,它都能提供全面的功能來滿足你的需求。
快速啟動(dòng)
要開始使用pdf-lib,首先確保你已經(jīng)安裝了相應(yīng)的npm包。在命令行中運(yùn)行以下命令:
npm install --save pdf-lib
或者如果你是yarn的使用者:
yarn add pdf-lib
實(shí)現(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('請(qǐng)選擇一個(gè)PDF文件');
return;
}
const arrayBuffer = await file.arrayBuffer();
const pdfDoc = await PDFLib.PDFDocument.load(arrayBuffer);
const pages = pdfDoc.getPages();
// 獲取當(dāng)前時(shí)間并格式化
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)';
// 計(jì)算文本寬度和高度
ctx.font = `${fontSize}px Arial`;
const textMetrics = ctx.measureText(watermarkText);
const textWidth = textMetrics.width;
const textHeight = fontSize;
// 計(jì)算旋轉(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對(duì)象
const image = new Image();
image.src = canvas.toDataURL('image/png');
// 添加水印到每一頁P(yáng)DF
for (const page of pages) {
const { width, height } = page.getSize();
// 計(jì)算新的水印尺寸,以便它可以跨越頁面的兩個(gè)相鄰邊緣
const cornerMargin = 50; // 角落與頁面邊緣之間的最小距離
const cornerSizeMultiplier = 0.5; // 控制水印相對(duì)于頁面尺寸的比例
const scale = 1; // 水印縮放比例
const cornerWidth = Math.min(width, height) * cornerSizeMultiplier * scale;
const cornerHeight = cornerWidth; // 假設(shè)是正方形水印
// 計(jì)算水印的新位置,使其跨越頁面的兩個(gè)相鄰邊緣
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對(duì)象
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實(shí)現(xiàn)pdf添加自定義水印功能的文章就介紹到這了,更多相關(guān)pdf-lib實(shí)現(xiàn)pdf添加自定義水印內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript發(fā)送短信驗(yàn)證碼實(shí)現(xiàn)代碼
我們?cè)谧?cè)賬號(hào),或者是參加活動(dòng)時(shí),都會(huì)向手機(jī)發(fā)送收短信驗(yàn)證碼,短信驗(yàn)證碼到底是如何實(shí)現(xiàn)的,本文為大家揭曉,并為大家分項(xiàng)1javascript發(fā)送短信驗(yàn)證碼實(shí)現(xiàn)代碼,感興趣的小伙伴們可以參考一下2015-11-11
js中關(guān)于new Object時(shí)傳參的一些細(xì)節(jié)分析
這里討論給Object傳參時(shí),其內(nèi)部的處理。參考:ECMA262 V5 15.2.2.12011-03-03
淺析JS中的 map, filter, some, every, forEach, for in, for of 用法總
本文是小編給大家總結(jié)的關(guān)于javascript中的map, filter, some, every, forEach, for in, for of 用法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-03-03
基于Bootstrap模態(tài)對(duì)話框只加載一次 remote 數(shù)據(jù)的解決方法
下面小編就為大家?guī)硪黄贐ootstrap模態(tài)對(duì)話框只加載一次 remote 數(shù)據(jù)的解決方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-07-07
微信jssdk踩坑之簽名錯(cuò)誤invalid signature
這篇文章主要介紹了微信jssdk踩坑之簽名錯(cuò)誤invalid signature,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05
Javascript 原型和繼承(Prototypes and Inheritance)
前面我們看到了如何使用 constructor 來初始化對(duì)象。如果這樣做,那么每一個(gè)創(chuàng)建的新對(duì)象都會(huì)對(duì)那些相同的屬性,方法建立一個(gè)獨(dú)立的副本。而實(shí)際上有更加有效的方法來指定方法,常量,以及其他一些可被所有該類的對(duì)象共享的屬性。2009-04-04

