Files
bentopdf/src/js/logic/add-watermark.ts

133 lines
7.2 KiB
TypeScript
Raw Normal View History

import { showLoader, hideLoader, showAlert } from '../ui.js';
import { downloadFile, readFileAsArrayBuffer, hexToRgb } from '../utils/helpers.js';
import { state } from '../state.js';
import { PDFDocument as PDFLibDocument, rgb, degrees, StandardFonts } from 'pdf-lib';
export function setupWatermarkUI() {
const watermarkTypeRadios = document.querySelectorAll('input[name="watermark-type"]');
const textOptions = document.getElementById('text-watermark-options');
const imageOptions = document.getElementById('image-watermark-options');
watermarkTypeRadios.forEach(radio => {
radio.addEventListener('change', (e) => {
// @ts-expect-error TS(2339) FIXME: Property 'value' does not exist on type 'EventTarg... Remove this comment to see the full error message
if (e.target.value === 'text') {
textOptions.classList.remove('hidden');
imageOptions.classList.add('hidden');
} else {
textOptions.classList.add('hidden');
imageOptions.classList.remove('hidden');
}
});
});
const opacitySliderText = document.getElementById('opacity-text');
const opacityValueText = document.getElementById('opacity-value-text');
const angleSliderText = document.getElementById('angle-text');
const angleValueText = document.getElementById('angle-value-text');
// @ts-expect-error TS(2339) FIXME: Property 'value' does not exist on type 'HTMLEleme... Remove this comment to see the full error message
opacitySliderText.addEventListener('input', () => opacityValueText.textContent = opacitySliderText.value);
// @ts-expect-error TS(2339) FIXME: Property 'value' does not exist on type 'HTMLEleme... Remove this comment to see the full error message
angleSliderText.addEventListener('input', () => angleValueText.textContent = angleSliderText.value);
const opacitySliderImage = document.getElementById('opacity-image');
const opacityValueImage = document.getElementById('opacity-value-image');
const angleSliderImage = document.getElementById('angle-image');
const angleValueImage = document.getElementById('angle-value-image');
// @ts-expect-error TS(2339) FIXME: Property 'value' does not exist on type 'HTMLEleme... Remove this comment to see the full error message
opacitySliderImage.addEventListener('input', () => opacityValueImage.textContent = opacitySliderImage.value);
// @ts-expect-error TS(2339) FIXME: Property 'value' does not exist on type 'HTMLEleme... Remove this comment to see the full error message
angleSliderImage.addEventListener('input', () => angleValueImage.textContent = angleSliderImage.value);
}
export async function addWatermark() {
// @ts-expect-error TS(2339) FIXME: Property 'value' does not exist on type 'Element'.
const watermarkType = document.querySelector('input[name="watermark-type"]:checked').value;
showLoader('Adding watermark...');
try {
const pages = state.pdfDoc.getPages();
let watermarkAsset = null;
if (watermarkType === 'text') {
watermarkAsset = await state.pdfDoc.embedFont(StandardFonts.Helvetica);
} else { // 'image'
// @ts-expect-error TS(2339) FIXME: Property 'files' does not exist on type 'HTMLEleme... Remove this comment to see the full error message
const imageFile = document.getElementById('image-watermark-input').files[0];
if (!imageFile) throw new Error('Please select an image file for the watermark.');
const imageBytes = await readFileAsArrayBuffer(imageFile);
if (imageFile.type === 'image/png') {
watermarkAsset = await state.pdfDoc.embedPng(imageBytes);
} else if (imageFile.type === 'image/jpeg') {
watermarkAsset = await state.pdfDoc.embedJpg(imageBytes);
} else {
throw new Error('Unsupported Image. Please use a PNG or JPG for the watermark.');
}
}
for (const page of pages) {
const { width, height } = page.getSize();
if (watermarkType === 'text') {
// @ts-expect-error TS(2339) FIXME: Property 'value' does not exist on type 'HTMLEleme... Remove this comment to see the full error message
const text = document.getElementById('watermark-text').value;
if (!text.trim()) throw new Error('Please enter text for the watermark.');
// @ts-expect-error TS(2339) FIXME: Property 'value' does not exist on type 'HTMLEleme... Remove this comment to see the full error message
const fontSize = parseInt(document.getElementById('font-size').value) || 72;
// @ts-expect-error TS(2339) FIXME: Property 'value' does not exist on type 'HTMLEleme... Remove this comment to see the full error message
const angle = parseInt(document.getElementById('angle-text').value) || 0;
// @ts-expect-error TS(2339) FIXME: Property 'value' does not exist on type 'HTMLEleme... Remove this comment to see the full error message
const opacity = parseFloat(document.getElementById('opacity-text').value) || 0.3;
// @ts-expect-error TS(2339) FIXME: Property 'value' does not exist on type 'HTMLEleme... Remove this comment to see the full error message
const colorHex = document.getElementById('text-color').value;
const textColor = hexToRgb(colorHex);
const textWidth = watermarkAsset.widthOfTextAtSize(text, fontSize);
page.drawText(text, {
x: (width - textWidth) / 2,
y: height / 2,
font: watermarkAsset,
size: fontSize,
color: rgb(textColor.r, textColor.g, textColor.b),
opacity: opacity,
rotate: degrees(angle),
});
} else {
// @ts-expect-error TS(2339) FIXME: Property 'value' does not exist on type 'HTMLEleme... Remove this comment to see the full error message
const angle = parseInt(document.getElementById('angle-image').value) || 0;
// @ts-expect-error TS(2339) FIXME: Property 'value' does not exist on type 'HTMLEleme... Remove this comment to see the full error message
const opacity = parseFloat(document.getElementById('opacity-image').value) || 0.3;
const scale = 0.5;
const imgWidth = watermarkAsset.width * scale;
const imgHeight = watermarkAsset.height * scale;
page.drawImage(watermarkAsset, {
x: (width - imgWidth) / 2,
y: (height - imgHeight) / 2,
width: imgWidth,
height: imgHeight,
opacity: opacity,
rotate: degrees(angle),
});
}
}
const newPdfBytes = await state.pdfDoc.save();
downloadFile(new Blob([newPdfBytes], { type: 'application/pdf' }), 'watermarked.pdf');
} catch (e) {
console.error(e);
showAlert('Error', e.message || 'Could not add the watermark. Please check your inputs.');
} finally {
hideLoader();
}
}