Skip to main content
Version: Version 5

Manage annotations in PDF

Extensive development effort required

This guide outlines a functionality that requires extensive development effort. Use the readily available features of the PDF Viewer SDK instead of implementing a viewer from scratch. Only use this guide if you want to implement your PDF viewer and customize it as much as possible. To test and implement the primary functionality of this SDK, review Getting started with the PDF Viewer SDK.

Add, modify, and delete annotations in a PDF document with the PDF Web SDK.

Steps to work with annotations in a PDF document:

  1. Initialize the SDK
  2. Create controller
  3. Open PDF
  4. Use AnnotationManager
  5. Full example

Before you begin

Initialize the SDK

Before instantiating objects and working with PDF Web SDK API, it needs to be initialized.

import { pdfToolsWebSdk, Pdf, UI } from '@pdftools/pdf-web-sdk';

async function initialize() {
await pdfToolsWebSdk.initialize({
path: './pdftools-web-sdk/',
});
}

initialize();

Create controller

A Pdf.Controller needs to be created to open the desired document. This controller is responsible for reading document information.

const controller = new Pdf.Controller();

Open PDF

Finally the document can be loaded to be later used to access the document information.

const pdfDocument = await controller.openDocument({
uri: '/pdf/WebViewer_Demo.pdf',
});

Use AnnotationManager

Overview

The AnnotationManager is a central interaction hub designed to handle annotation-related operations within a document. It serves as a bridge between user interactions and the underlying document structure, facilitating dynamic changes to annotations based on user actions. It can be access through the annotations property in the Pdf.Document.

Get annotations

Annotation objects can be retrieved via AnnotationManager.getAll() or AnnotationManager.getAllOnPage(page: number).

The following code snippet shows how to iterate through the annotations on a specific page:

const annotations = await pdfDocument.annotations.getAllOnPage(1);
console.log(annotationsAfter);
annotations.forEach((annotation) => {
// Do something with the annotation
});

Add annotations

Annotation objects can be added individually via AnnotationManager.add(a: Annotation) or using the overload AnnotationManager.add(arr: Annotation[]).

The following code snippet shows how to add annotations to a document:

// Add a single annotation
await pdfDocument.annotations.add(
new Pdf.Annotations.FreeTextAnnotation({
page: pdfDocument.pages.getByNumber(1),
boundingBox: new Pdf.Geometry.Rectangle(100, 100, 100, 100),
content: 'First free text annotation',
author: 'John Doe',
subject: 'First subject',
})
);

// Add multiple annotations
await pdfDocument.annotations.add([
new Pdf.Annotations.FreeTextAnnotation({
page: pdfDocument.pages.getByNumber(2),
boundingBox: new Pdf.Geometry.Rectangle(200, 200, 200, 200),
content: 'Second free text annotation',
author: 'John Doe',
subject: 'Second subject',
}),
new Pdf.Annotations.FreeTextAnnotation({
page: pdfDocument.pages.getByNumber(3),
boundingBox: new Pdf.Geometry.Rectangle(300, 300, 300, 300),
content: 'Third free text annotation',
author: 'John Doe',
subject: 'Third subject',
}),
]);
note

When new Annotation objects are created, they are not automatically added to the document structure, but instead they are only existing as losely connected objects. To effectively add the annotations to the document and to be able to save the document with the new annotations AnnotationManager.add or respectively AnnotationManager.update must be called.

This decoupling of annotation creation and adding is done for flexibilty and performance reasons. By deferring annotation updates until explicitly requested, unnecessary rendering operations and updates of the document structure can be avoided.

Modify annotations

Updating Annotation objects involves modifying their properties and then calling AnnotationManager.update(a: Annotation) or respectively AnnotationManager.update(arr: Annotation[]) method.

The following code snippet shows how to edit a single annotation in a document.

// Get annotations
const annotationsBefore = await pdfDocument.annotations.getAll();
console.log(annotationsBefore);
// Edit an annotation
annotationsBefore[0].content = annotationsBefore[0].content + ' (Edited)';
annotationsBefore[0].boundingBox.topLeft.x += 100;
// Apply changes
await pdfDocument.annotations.update(annotationsBefore[0]);
// Get annotations again
const annotationsAfterEdit = await pdfDocument.annotations.getAll();
console.log(annotationsAfterEdit);
});
note

When Annotation objects are modified, changes are not automatically applied to the document, but instead changes are only cached in the Annotation object. To make the changes effective and to be able to save the document with the modifications AnnotationManager.update must be called.

This decoupling of annotation modification and updating is done for flexibilty and performance reasons. By deferring annotation updates until explicitly requested, unnecessary rendering operations and updates of the document structure can be avoided.

Delete Annotations

Annotation objects can be deleted individually via AnnotationManager.delete(a: Annotation) or using the overload AnnotationManager.delete(arr: Annotation[]).

The following code snippet shows how to delete an annotations from a document.

// Get annotations
const annotationsBefore = await pdfDocument.annotations.getAll();
console.log(annotationsBefore);
// Delete a single annotation
await pdfDocument.annotations.delete(annotations[0]);
// Delete multiple annotation
await pdfDocument.annotations.delete([annotations[1], annotations[2]]);
const annotationsAfterDelete = await pdfDocument.annotations.getAll();
console.log(annotationsAfterDelete);

Full example

This full sample demonstrates how to continously add, update, and delete annotations in document.

import { pdfToolsWebSdk, Pdf } from '@pdftools/pdf-web-sdk';

pdfToolsWebSdk.initialize().then(async () => {
const controller = new Pdf.Controller();
const pdfDocument = await controller.openDocument({
uri: '/pdf/WebViewer_Demo.pdf',
});

let annotationCounter = 0;
setTimeout(() => {
// move all annotations a bit to the right
const annotationsBefore = await pdfDocument.annotations.getAll();
annotationsBefore.forEach((a) => {
a.boundingBox.topLeft.x += 10;
});
await pdfDocument.annotations.update(annotationsBefore);
const annotationsUpdated = await pdfDocument.annotations.getAll();

// if last annotations reaches end of the page -> delete it
const lastAnnotation = annotationsUpdated[annotationsUpdated.length-1];
if(lastAnnotation.boundingBox.topLeft.x > 500)
{
pdfDocument.delete(lastAnnotation);
}

// if first annotation has moved enough to the right -> insert a new one on the left
const firstAnnotation = annotationsUpdated[0];
if(firstAnnotation.boundingBox.topLeft.x > 100)
{
annotationCounter++;
pdfDocument.add(new Pdf.Annotations.FreeTextAnnotation({
page: doc.pages.getByNumber(1),
boundingBox: new Pdf.Geometry.Rectangle(10, 100, 50, 50),
content: `Annotation #${annotationCounter}`,
author: 'John Doe',
subject: `Subject #${annotationCounter}`,
}));
}
}, 100);
});