DocsVuePluginsAnnotation

Annotation Plugin

The Annotation Plugin provides a comprehensive framework for adding, editing, and managing annotations within a PDF document. It supports a wide range of common annotation types, including text markups (highlight, underline), free-hand drawings (ink), shapes (squares, circles), and more.

The plugin is built on an extensible “Tool” system, allowing you to define and customize different annotation behaviors and appearances.

Installation

This plugin has several dependencies that must be installed to handle user interactions and manage state. The history plugin is optional but recommended for undo/redo functionality.

npm install @embedpdf/plugin-annotation @embedpdf/plugin-interaction-manager @embedpdf/plugin-selection @embedpdf/plugin-history

Registration

Import AnnotationPluginPackage and its dependencies. It is crucial to register the dependencies before the annotation plugin itself.

import { createPluginRegistration } from '@embedpdf/core' import { EmbedPDF } from '@embedpdf/core/vue' // ... other imports import { InteractionManagerPluginPackage } from '@embedpdf/plugin-interaction-manager/vue' import { SelectionPluginPackage } from '@embedpdf/plugin-selection/vue' import { HistoryPluginPackage } from '@embedpdf/plugin-history/vue' import { AnnotationPluginPackage } from '@embedpdf/plugin-annotation/vue' const plugins = [   // ... other essential plugins   createPluginRegistration(LoaderPluginPackage, { /* ... */ }),   createPluginRegistration(RenderPluginPackage),   // Register dependencies first   createPluginRegistration(InteractionManagerPluginPackage),   createPluginRegistration(SelectionPluginPackage),   createPluginRegistration(HistoryPluginPackage),   // Register and configure the annotation plugin   createPluginRegistration(AnnotationPluginPackage, {     // Optional: Set the author name for created annotations     annotationAuthor: 'Jane Doe',   }), ]

Usage

The plugin works by combining a UI component to render the annotations with a composable to manage the annotation tools and state.

1. The <AnnotationLayer /> Component

This component is responsible for rendering all annotations and handling user interactions like creating, selecting, moving, and resizing. It must be placed inside the <Scroller />’s default slot and wrapped by a <PagePointerProvider> to correctly process pointer events.

<script setup lang="ts"> import { PagePointerProvider } from '@embedpdf/plugin-interaction-manager/vue'; import { AnnotationLayer } from '@embedpdf/plugin-annotation/vue'; </script> <template> <Scroller> <template #default="{ page }"> <PagePointerProvider :page-index="page.pageIndex" :page-width="page.width" :page-height="page.height" :rotation="page.rotation" :scale="page.scale" > <RenderLayer :page-index="page.pageIndex" :scale="page.scale" style="pointer-events: none" /> <SelectionLayer :page-index="page.pageIndex" :scale="page.scale" style="pointer-events: none" /> <AnnotationLayer :page-index="page.pageIndex" :scale="page.scale" :page-width="page.width" :page-height="page.height" :rotation="page.rotation" /> </PagePointerProvider> </template> </Scroller> </template>

2. Building an Annotation Toolbar

The useAnnotationCapability composable provides all the necessary methods to control the plugin. You can build a toolbar that allows users to select an “active tool” (like a pen or highlighter) and perform actions like deleting a selected annotation.

<script setup lang="ts"> import { ref, onMounted, onUnmounted } from 'vue'; import { useAnnotationCapability } from '@embedpdf/plugin-annotation/vue'; const { provides: annotationApi } = useAnnotationCapability(); const activeTool = ref<string | null>(null); const canDelete = ref(false); let unsub1: () => void; let unsub2: () => void; onMounted(() => { if (!annotationApi.value) return; unsub1 = annotationApi.value.onActiveToolChange(tool => (activeTool.value = tool?.id ?? null)); unsub2 = annotationApi.value.onStateChange(state => (canDelete.value = !!state.selectedUid)); }); onUnmounted(() => { unsub1?.(); unsub2?.(); }); const setActiveTool = (toolId: string) => { annotationApi.value?.setActiveTool(activeTool.value === toolId ? null : toolId); } </script> <template> <div> <button @click="setActiveTool('highlight')">Highlighter</button> <button @click="setActiveTool('ink')">Pen</button> </div> </template>

3. Creating Custom Tools

You can extend the plugin’s functionality by adding your own tools. For example, you could create a custom image stamp. This is done by calling addTool on the plugin’s capability, often within the @initialized event handler of the <EmbedPDF> component.

<script setup lang="ts"> import type { PluginRegistry } from '@embedpdf/core'; import { AnnotationPlugin, type AnnotationTool } from '@embedpdf/plugin-annotation/vue'; import { PdfAnnotationSubtype, type PdfStampAnnoObject } from '@embedpdf/models'; const handleInitialized = (registry: PluginRegistry) => { const annotationApi = registry.getPlugin<AnnotationPlugin>('annotation')?.provides(); annotationApi?.addTool<AnnotationTool<PdfStampAnnoObject>>({ id: 'stampApproved', name: 'Approved Stamp', interaction: { exclusive: false, cursor: 'copy' }, matchScore: () => 0, // Doesn't match existing annotations defaults: { type: PdfAnnotationSubtype.STAMP, imageSrc: '/images/approved-stamp.png', // URL to your stamp image }, }); }; </script> <template> <EmbedPDF :engine="engine" :plugins="plugins" @initialized="handleInitialized"> </EmbedPDF> </template>

Live Example

The example below includes a toolbar for selecting different annotation tools (highlight, ink pen, square) and a delete button that becomes active when an annotation is selected.

API Reference

Configuration (AnnotationPluginConfig)

OptionTypeDescription
annotationAuthorstringSets the author name for all created annotations. Default: 'Guest'
autoCommitbooleanIf true, annotation changes are automatically saved to the engine. Default: true
toolsAnnotationTool[]An array of custom annotation tools to add or override default tools.
colorPresetsstring[]A list of hex color strings to be used in a color picker UI.
deactivateToolAfterCreatebooleanIf true, the active tool is deselected after an annotation is created. Default: false
selectAfterCreatebooleanIf true, a newly created annotation is automatically selected. Default: true

Component: <AnnotationLayer />

The primary component for rendering and interacting with annotations.

PropTypeDescription
pageIndexnumber(Required) The page index this layer corresponds to.
scalenumber(Required) The current zoom scale of the page.
rotationnumber(Required) The current rotation of the page.
pageWidthnumber(Required) The unscaled width of the PDF page.
pageHeightnumber(Required) The unscaled height of the PDF page.
selectionOutlineColorstringThe color of the outline around a selected annotation. Default: '#007ACC'

Scoped Slot: selection-menu

The <AnnotationLayer> provides a scoped slot to render a custom menu when an annotation is selected.

PropTypeDescription
itemRedactionItemThe selected annotation data.
selectedbooleantrue if an annotation is currently selected.
menuWrapperPropsobjectVue props to bind to your menu’s wrapper element for positioning.
rectRectThe bounding box of the selected annotation.

Composable: useAnnotationCapability()

Connects your components to the annotation plugin’s state and methods.

Returns

PropertyTypeDescription
providesRef<AnnotationCapability | null>A ref object with methods to control the plugin, or null if not ready.

AnnotationCapability Methods

A selection of key methods available on the provides.value object:

MethodDescription
setActiveTool(toolId)Activates an annotation tool (e.g., 'ink', 'highlight'). Pass null to deactivate.
getActiveTool()Returns the currently active AnnotationTool object, or null.
addTool(tool)Registers a new custom AnnotationTool.
deleteAnnotation(..)Deletes an annotation from a page.
getSelectedAnnotation()Returns the currently selected TrackedAnnotation object, or null.
onStateChange(cb)Subscribes to any change in the annotation state. Returns an unsubscribe function.
onAnnotationEvent(cb)Subscribes to events like annotation creation, updates, or deletion. Returns an unsubscribe function.
Last updated on October 8, 2025

Need Help?

Join our community for support, discussions, and to contribute to EmbedPDF's development.