How to Add Watermarks to PDF Files in the Browser with Vue 3 and pdf-lib

javascript dev.to

Adding watermarks to PDFs in the browser involves positioning, opacity control, and handling both text and image watermarks. Here's how to build a browser-based PDF watermark tool with Vue 3 and pdf-lib.

The challenge: Positioning and opacity

Watermark implementation requires:

  1. Drawing text or images on each page
  2. Controlling opacity for subtle background effects
  3. Supporting rotation and positioning
  4. Handling both text and image watermarks

The stack

  • Vue 3 with Composition API
  • pdf-lib for PDF manipulation
  • Vite for bundling

The core implementation

<script setup lang="ts">
import { ref } from 'vue'
import { PDFDocument, rgb, StandardFonts } from 'pdf-lib'

const file = ref<File | null>(null)
const watermarkText = ref('CONFIDENTIAL')
const opacity = ref(0.2)
const rotation = ref(45)
const watermarking = ref(false)
const result = ref<Uint8Array | null>(null)

async function addWatermark() {
  if (!file.value) return
  watermarking.value = true

  const arrayBuffer = await file.value.arrayBuffer()
  const pdf = await PDFDocument.load(arrayBuffer)
  const pages = pdf.getPages()
  const font = await pdf.embedFont(StandardFonts.Helvetica)

  for (const page of pages) {
    const { width, height } = page.getSize()

    page.drawText(watermarkText.value, {
      x: width / 2 - 100,
      y: height / 2,
      size: 50,
      font,
      color: rgb(0.5, 0.5, 0.5),
      opacity: opacity.value,
      rotate: { type: 'degrees', angle: rotation.value },
    })
  }

  result.value = await pdf.save()
  watermarking.value = false
}
</script>
Enter fullscreen mode Exit fullscreen mode

Key implementation details

1. Text watermark

Use pdf-lib's drawText with opacity and rotation:

page.drawText(text, {
  x: width / 2 - textWidth / 2,
  y: height / 2,
  size: 50,
  font,
  color: rgb(0.5, 0.5, 0.5),
  opacity: 0.2,
  rotate: { type: 'degrees', angle: 45 },
})
Enter fullscreen mode Exit fullscreen mode

2. Image watermark

For image watermarks, embed and draw the image:

const imageData = await file.arrayBuffer()
const image = await pdf.embedPng(imageData)
const { width, height } = page.getSize()

page.drawImage(image, {
  x: 0,
  y: 0,
  width: width * 0.5,
  height: height * 0.5,
  opacity: opacity.value,
})
Enter fullscreen mode Exit fullscreen mode

3. Multi-page application

Apply watermark to all pages or specific pages:

const pages = pdf.getPages()
for (const page of pages) {
  // Apply watermark to each page
}
Enter fullscreen mode Exit fullscreen mode

4. Opacity control

pdf-lib supports opacity in the 0-1 range:

opacity: Number(opacity.value) // 0.0 to 1.0
Enter fullscreen mode Exit fullscreen mode

Limitations

No real-time preview

pdf-lib doesn't support real-time preview without rendering.

Solution: Show a static preview or render thumbnails separately.

Limited positioning options

Basic text positioning is supported, but complex layouts may need more.

Solution: Calculate positions based on page dimensions.

Large files

Very large PDFs may cause memory issues.

Solution: Process in smaller batches or use Web Workers.

Summary

Building a browser-based PDF watermark tool involves:

  1. Loading the PDF with pdf-lib
  2. Drawing text or images on each page
  3. Controlling opacity and rotation
  4. Saving and downloading the watermarked PDF

Try it at en.sotool.top/watermark.

Source: dev.to

arrow_back Back to Tutorials