Manage annotations in PDF
Add, modify, and delete annotations in a PDF document with the PDF Web SDK.
Steps to work with annotations in a PDF document:
If you prefer to test a demo or would like to explore the basic functionalities of this SDK, review Getting started with the PDF Viewer SDK and learn how to make static assets available.
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',
}),
]);
When new Annotation objects are created, they are not automatically added to the document structure, but instead they are only existing as loosely 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 flexibility 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);
});
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 flexibility 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 continuously add, update, and delete annotations in a 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);
});