Some test text!

Search
Hamburger Icon

Web / Guides / FreeText & callouts

FreeText & Callout Annotations

FreeText annotations allow users to write text onto the page. Callout annotations are actually FreeText annotations underneath. The main difference is they will have a line ending that points to something on the page that is meant to be referenced.

FreeText annotation

Contrary to most rectangular annotations, FreeText annotations are actually composed of points as opposed to a rectangle. A FreeText annotation is initialized with two points whereas a callout has a total of five points (one each for joint, knee, and end). Another difference between the two is the intent of the annotation which indicates what type of annotation it should be (callout or normal FreeText).

Instantiation

FreeText

WebViewer(...)
  .then(instance => {
    const { documentViewer, annotationManager, Annotations } = instance.Core;

    documentViewer.addEventListener('annotationsLoaded', () => {
      const annot = new Annotations.FreeTextAnnotation(Annotations.FreeTextAnnotation.Intent.FreeText, {
        PageNumber: 1,
        X: 100,
        Y: 50,
        Width: 200,
        Height: 50,
        TextAlign: 'center',
        TextVerticalAlign: 'center',
        TextColor: new Annotations.Color(255, 0, 0, 1),
        StrokeColor: new Annotations.Color(0, 255, 0, 1),
      });

      annot.setContents(`Visited: ${new Date()}`);

      annotationManager.addAnnotation(annot);
      annotationManager.redrawAnnotation(annot);
    });
  });

Callout

WebViewer(...)
  .then(instance => {
    const { documentViewer, annotationManager, Annotations } = instance.Core;

    documentViewer.addEventListener('annotationsLoaded', () => {
      const annot = new Annotations.FreeTextAnnotation(Annotations.FreeTextAnnotation.Intent.FreeTextCallout, {
        PageNumber: 1,
        TextAlign: 'center',
        TextVerticalAlign: 'center',
        TextColor: new Annotations.Color(255, 0, 0, 1),
        StrokeColor: new Annotations.Color(0, 255, 0, 1),
      });

      annot.setPathPoint(0, 500, 25);  // Callout ending (start)
      annot.setPathPoint(1, 425, 75);  // Callout knee
      annot.setPathPoint(2, 300, 75);  // Callout joint
      annot.setPathPoint(3, 100, 50);  // Top-left point
      annot.setPathPoint(4, 300, 100); // Bottom-right point

      annot.setContents(`Visited: ${new Date()}`);

      annotationManager.addAnnotation(annot);
      annotationManager.redrawAnnotation(annot);
    });
  });

XFDF

Element name: freetext

<freetext page="0" rect="163.440,623.270,348.060,704.660" flags="print" name="5b9b1430-c04f-bc6d-5457-f90c7793997f" title="Guest" subject="Free Text" date="D:20220525164654-07'00'" width="0.75" creationdate="D:20220525164652-07'00'" TextColor="#E44234" FontSize="12">
  <trn-custom-data bytes="{"trn-wrapped-text-lines":"[\"Insert text here \"]"}"/>
  <contents>Insert text here</contents>
  <contents-richtext>
      <body>
          <p>
              <span>Insert text here</span>
          </p>
      </body>
  </contents-richtext>
  <appearance xmlns="http://www.w3.org/1999/xhtml">...</appearance>
  <defaultappearance>0.894 0.259 0.204 rg /Helvetica 12 Tf</defaultappearance>
  <defaultstyle>font: Helvetica 12pt; text-align: left; text-vertical-align: top; color: #E44234</defaultstyle>
</freetext>

Required properties

PageNumber

Gets or sets the page number of a document that the annotation appears on.

X

Gets or sets the annotation's x-axis position.

This property can be initialized through an object initializer but works best on regular FreeText annotations.

Y

Gets or sets the annotation's y-axis position.

This property can be initialized through an object initializer but works best on regular FreeText annotations.

Width

Gets or sets the width of the annotation.

This property can be initialized through an object initializer but works best on regular FreeText annotations. Setting this on a callout will scale it up or down.

Height

Gets or sets the height of the annotation.

This property can be initialized through an object initializer but works best on regular FreeText annotations. Setting this on a callout will scale it up or down.

Notable properties

For the full list of properties, please visit the annotation's API docs.

[static] AutoSizeTypes

An enum with possible auto-size types. See setAutoSizeType to change the autosizing behavior.

Values:

  • NONE
  • AUTO
  • FIXED_WIDTH
  • FIXED_HEIGHT

[static] Intent

An enum with possible freetext intents.

Values:

  • FreeText
  • FreeTextCallout

Font

The font to use for the annotation's text. Fonts supported by the canvas/CSS only.

FontSize

The font size to use for the annotation's text, specified like a CSS font size.

TextAlign

The horizontal alignment of the annotation's text.

Values:

  • left
  • center
  • right
  • justify

TextVerticalAlign

The vertical alignment of the annotation's text (top, bottom, center). Default: top.

This property is only available in WebViewer 8.2+.

TextColor

The color of the text in the annotation.

StrokeColor

Gets or sets the color of the annotation's stroke.

FillColor

Gets or sets the color of the annotation's interior.

Style

Gets or sets the border style of an annotation. Possible styles include:

  • solid
  • dash
  • cloudy

Dashes

Gets or sets the border dash style of an annotation. This expects a string representing the length of dashes and spacing inbetween, delimited by commas (ex. 3, 3). You can specify any amount of lengths but, an odd number of values will be made even by cloning it as a second set. To understand further, you can read more about the setLineDash API.

StrokeThickness

Gets or sets the width of the annotation's stroke outline.

autoSizeProperties

Object that contains all the flags to customize the auto-sizing behavior.

Author

The author of the annotation.

Color

Gets or sets the annotation's stroke color.

Hidden

Gets or sets whether the annotation is hidden.

Invisible

Gets or sets whether the annotation is invisible, only if it is an unknown annotation type. Generally for hiding annotations you should use "Hidden".

IsClickableOutsideRect

Gets or sets whether any parts of the annotation drawn outside of the rect are clickable.

Listable

Gets or sets whether the annotation should be listed in annotation lists. If set to false, the annotation will also become unselectable.

Locked

Gets or sets whether the annotation is locked or not. If it's locked it can't be edited or deleted, but the note can be edited.

LockedContents

Gets or sets whether the annotation contents are locked or not. If the contents are locked then note can't be edited but the annotation can be edited or deleted.

NoDelete

Gets or sets if this annotation can be deleted.

NoMove

Gets or sets whether or not the annotation can be moved.

NoResize

Gets or sets if this annotation can be resized by the user.

NoRotate

Gets or sets if this annotation can be rotated.

NoView

Gets or sets whether the annotation is visible on the screen. Differs from Hidden in that it can still be printed if the print flag is set.

NoZoom

Gets or sets if this annotation scales with the page.

Printable

Gets or sets whether the annotation should be displayed when printing the page.

ReadOnly

Gets or sets whether the annotation is readonly or not. If it's readonly both the annotation itself and its note can't be edited or deleted.

ToggleNoView

Gets or sets whether the ToggleNoView flag is set on the annotation.

Useful methods

getPath

To read the path or points of the FreeText and/or callout annotation, you can use getPath to get an array of points. FreeText annotations will contain two points whereas callouts will contain five (line ending, knee, joint, top left of content box, and bottom right of content box).

WebViewer(...)
  .then(instance => {
    const { documentViewer, annotationManager, Annotations } = instance.Core;

    documentViewer.addEventListener('annotationsLoaded', () => {
      const annotList = annotationManager.getAnnotationsList();
      annotList.forEach(annot => {
        if (annot instanceof Annotations.FreeTextAnnotation) {
          const points = annot.getPath();
          points.forEach(point => {
            // Work with points
          });
        }
      });
    });
  });

setPath

Rather than setting individual points to set up a FreeText annotation, it is possible to set the entire path of points with setPath.

getIntent

To know what kind of FreeTextAnnotation you are working with, you can read the intent with getIntent which can be matched to either FreeText or FreeTextCallout.

setIntent

You can set the intent of a FreeText annotation with the setIntent API after initialization. You will need to adjust the path of the annotation to have the exact points it requires or the annotation may not render properly.

WebViewer(...)
  .then(instance => {
    const { documentViewer, annotationManager, Annotations } = instance.Core;

    documentViewer.addEventListener('annotationsLoaded', () => {
      const annotList = annotationManager.getAnnotationsList();
      annotList.forEach(annot => {
        if (annot instanceof Annotations.FreeTextAnnotation) {
          annot.setIntent(Annotations.FreeTextAnnotation.Intent.FreeText);
          annot.setPath(annot.getPath().slice(0, 2));
        }
      });
    });
  });

getContents

As the content of the FreeText annotation is the primary focus, there should be a way to read it. This can be done with the getContents API.

WebViewer(...)
  .then(instance => {
    const { documentViewer, annotationManager, Annotations } = instance.Core;

    documentViewer.addEventListener('annotationsLoaded', () => {
      const annotList = annotationManager.getAnnotationsList();
      annotList.forEach(annot => {
        if (annot instanceof Annotations.FreeTextAnnotation) {
          const contents = annot.getContents();
          // Check contents
        }
      });
    });
  });

setContents

Most of the time, you will be creating a FreeText annotation with text. To set the text, you use the setContents method to provide the string content.

getPathPoint

If you know which point of the annotation path you would like to get, you can use getPathPoint with the point index to retrieve the point.

setPathPoint

Setting the path points on the freetext/callout annotation can be done through the setPathPoint. This can be used to initialize the points of a the annotation if that was not done at the start. Please note that there will be two points in the annotation path by default, initializing it in the top left corner with a size of one.

WebViewer(...)
  .then(instance => {
    const { documentViewer, annotationManager, Annotations } = instance.Core;

    documentViewer.addEventListener('annotationsLoaded', () => {
      const annotList = annotationManager.getAnnotationsList();
      annotList.forEach(annot => {
        if (annot instanceof Annotations.FreeTextAnnotation) {
          annot.setPathPoint(0, 50, 100);
          annot.setPathPoint(1, 250, 150);
        }
      });
    });
  });

setStartStyle

This is only for callout annotations. Callout annotations have a default line ending that is an arrow. In actuality, this is the start of the path and can be changed with the setStartStyle. You can find the possible line endings with the LineEndType constant.

WebViewer(...)
  .then(instance => {
    const { documentViewer, annotationManager, Annotations } = instance.Core;

    documentViewer.addEventListener('annotationsLoaded', () => {
      const annotList = annotationManager.getAnnotationsList();
      annotList.forEach(annot => {
        if (annot instanceof Annotations.FreeTextAnnotation) {
          annot.setLineEndType(Annotations.LineEndType.DIAMOND);
        }
      });
    });
  });

switchToAutoFontSize

This method is used to switch the font size behavior of the free text annotation to "auto," which means that the font size will adapt dynamically to the size of the annotation's bounding box when it is resized.

WebViewer(...)
  .then(instance => {
    const { documentViewer, annotationManager, Annotations } = instance.Core;

    documentViewer.addEventListener('annotationsLoaded', () => {
      const annotList = annotationManager.getAnnotationsList();
      annotList.forEach(annot => {
        if (annot instanceof Annotations.FreeTextAnnotation) {
          annot.switchToAutoFontSize();
        }
      });
    });
  });
WebViewer(...)
  .then(instance => {
    const { docViewer, annotManager, Annotations } = instance;

    docViewer.addEventListener('annotationsLoaded', () => {
      const annotList = annotManager.getAnnotationsList();
      annotList.forEach(annot => {
        if (annot instanceof Annotations.FreeTextAnnotation) {
          annot.FontSize = '0px'
        }
      });
    });
  });

getCalculatedFontSize

This method retrieves the font size that has been dynamically calculated to fit the content within the bounding box of the free text annotation when switchToAutoFontSize is used to enable auto-sizing of the font size. If switchToAutoFontSize has not been called, it will return the current font size.

WebViewer(...)
  .then(instance => {
    const { annotationManager, Annotations } = instance.Core;

    annotationManager.addEventListener('annotationSelected', (annotations, action) => {
        if (action === 'selected' && annotations[0] instanceof Annotations.FreeTextAnnotation) {
           annotations[0].switchToAutoFontSize(); 
        }
    });

    annotationManager.addEventListener('annotationChanged', (annotations, action) => {
        if (action === 'modify' && annotations[0] instanceof Annotations.FreeTextAnnotation) {
          console.log(annotations[0].getCalculatedFontSize());
        }
    });
  });

Other notes

FreeText annotations created through the FreeTextCreateTool can be created one of two ways: drawing a rectangle or by clicking. This changes how FreeText annotations resize relative to their content. By creating a FreeText annotation by drawing a rectangle, it has a fixed size and does not autosize to content. The latter will resize relative to the content.

Trial setup questions? Ask experts on Discord
Need other help? Contact Support
Pricing or product questions? Contact Sales