Skip to content

Annotation Component Configurator

Overview

AnnotComponentConfig is the core configuration object in Foxit PDF SDK for Web for controlling the interactive behavior of annotation components. By updating the configuration dynamically at runtime, developers can flexibly control whether users can move, rotate, scale, and otherwise interact with annotations.

NOTE

The configuration here mainly controls UI interaction capabilities such as dragging and resizing. It is separate from document permissions such as read-only mode or disabled annotations, so it should be designed together with the permission APIs.

Core Parts

1. AnnotComponentConfig API

AnnotComponentConfig defines the available configuration fields for annotation components. Its interface is as follows:

typescript
export interface AnnotComponentConfig {
    moveable: boolean; // Whether moving is allowed
    rotatable: boolean; // Whether rotation is allowed
    resizable: boolean; // Whether resizing is allowed
    enableDiagonally: boolean; // Whether diagonal resizing is allowed
    moveDirection: string; // Restriction on move direction
}

2. CustomOptionsUpdater Class

CustomOptionsUpdater is used to update the configuration above dynamically at runtime. It is the core class used together with entry points such as updateGetAnnotComponentConfig.

Configuration Options

moveable

  • Type: boolean
  • Default value:
    • Area Highlight: false
    • All other annotation types: true
  • Supported annotation types: stamp, circle, ink, link, square, screen, redact, Area Highlight, widget
  • Purpose: Controls whether users can drag the annotation in the UI

rotatable

  • Type: boolean
  • Default value: true
  • Supported annotation types: stamp
  • Purpose: Controls whether users can rotate the annotation in the UI

resizable

  • Type: boolean
  • Default value: true
  • Supported annotation types: stamp, circle, ink, link, square, screen, redact, Area Highlight, widget
  • Purpose: Controls whether users can resize the annotation in the UI

enableDiagonally

  • Type: boolean
  • Default value: true
  • Supported annotation types: ink, link, square, screen, redact, Area Highlight, widget
  • Purpose: When resizable is true, controls whether diagonal resize handles are shown

enableFrame

  • Type: boolean
  • Default value: false
  • Supported annotation types: stamp
  • Purpose: Controls whether resizing is allowed through the midpoint handles on the top, bottom, left, and right edges, as distinct from diagonal handles

moveDirection

  • Type: string
  • Default value: 'All'
  • Supported annotation types: stamp, circle, ink, link, square, screen, redact, Area Highlight, widget
  • Available values:
    • 'horizontal' - Only horizontal movement is allowed
    • 'vertical' - Only vertical movement is allowed
    • 'all' - Movement in any direction is allowed
  • Note: When moveDirection is not set to 'all', the annotation cannot be moved across pages.

Usage

1. Configure During Initialization

When creating a PDFViewer instance, you can set the initial behavior through the customs.getAnnotComponentConfig callback:

javascript
const pdfViewer = new PDFViewer({
    customs: {
        getAnnotComponentConfig: function (annotComponent, props) {
            const annot = annotComponent.getModel();
            const annotType = annot.getType();

            // Return different configurations by annotation type
            switch (annotType) {
                case "square":
                    return { moveable: false, resizable: true };
                case "highlight":
                    if (annot.isArea()) {
                        return { moveable: false };
                    }
                    break;
                case "freetext":
                    return { moveable: false, resizable: false };
                case "strikeout":
                    return { adjustable: false }; // Text markup annotations support only adjustable
                case "line":
                    return { moveable: false, resizable: false }; // Line, arrow, polyline, polygon, cloud, and similar types support these two options
                case "text":
                case "fileattachment":
                    return { moveable: false }; // Text annotations and file attachment annotations usually configure only moveable
            }
            return {}; // Returning an empty object means using the default configuration for the annotation type
        },
    },
});

2. Dynamically Update at Runtime

Use CustomOptionsUpdater to override or adjust the configuration at runtime:

javascript
// Get the configuration updater
const updater = pdfViewer.getCustomOptionsUpdater();

// Dynamically update the getAnnotComponentConfig callback
updater.updateGetAnnotComponentConfig(function (annotComponent, props) {
    const annot = annotComponent.getModel();
    const annotType = annot.getType();

    // Return configuration based on business logic
    if (annotType === "square") {
        return {
            moveable: false,
            resizable: true,
            enableDiagonally: false,
        };
    } else if (annotType === "highlight" && annot.isArea()) {
        return {
            moveable: false,
            moveDirection: "horizontal", // Allow horizontal dragging only
        };
    }

    return {};
});

Support Matrix by Annotation Type

Annotation TypemoveablerotatableresizableenableDiagonallyenableFramemoveDirection
stamp
circle
ink
link
square
screen
redact
Area Highlight
widget
freetext (text box, note)
freetext (typewriter)
text
fileattachment
textmarks

TextMarks including underline, text highlight, strikeout, and squiggly, but excluding caret, support only the adjustable configuration item.

Typical Scenarios

Note: getCurrentUserRole and getUserPermissions in the examples below are placeholder functions. Replace them with the actual implementations used in your project.

1. Document Review Mode

javascript
// Prevent reviewers from changing annotation shape- and position-related interactions
updater.updateGetAnnotComponentConfig(function (annotComponent, props) {
    const annot = annotComponent.getModel();
    const userRole = getCurrentUserRole(); // Get the current user role

    if (userRole === "reviewer") {
        return {
            moveable: false,
            resizable: false,
            rotatable: false,
        };
    }

    return {};
});

2. Restrict Capabilities by Annotation Type

javascript
// Disable or limit interaction for specific annotation types
updater.updateGetAnnotComponentConfig(function (annotComponent, props) {
    const annot = annotComponent.getModel();
    const annotType = annot.getType();

    // Disable dragging for all link annotations
    if (annotType === "link") {
        return { moveable: false };
    }

    // Allow stamp annotations to move horizontally only
    if (annotType === "stamp") {
        return { moveDirection: "horizontal" };
    }

    return {};
});

3. Dynamic Control Based on Business Permissions

javascript
// Return configuration dynamically based on business-side permission objects
updater.updateGetAnnotComponentConfig(function (annotComponent, props) {
    const annot = annotComponent.getModel();
    const userPermissions = getUserPermissions();

    if (!userPermissions.canEditAnnotations) {
        return {
            moveable: false,
            resizable: false,
            rotatable: false,
        };
    }

    if (!userPermissions.canMoveAnnotations) {
        return { moveable: false };
    }

    return {};
});

Notes

  1. Configuration priority: Logic set at runtime through updateGetAnnotComponentConfig overrides the result from customs.getAnnotComponentConfig during initialization. The most recently registered callback takes effect, so avoid overwriting earlier branches accidentally.
  2. Cross-page movement: When moveDirection is not 'all', annotations cannot be dragged across pages.
  3. Performance: The callback is triggered frequently during annotation interaction. Keep the logic lightweight, and avoid heavy computation or remote synchronization inside it.
  4. Type compatibility: Different annotation types support different fields. Unsupported fields in the returned object may be ignored. Confirm support against the table above and the API documentation.
  5. Difference from permissions: This set of options is an interaction switch. It cannot replace PDF document permissions or the SDK permission model. Scenarios such as read-only documents still require permission-related APIs.