Flip annotations horizontally and vertically feature

PDF.js Express Version

Detailed description of issue
Flip Annotations horizontally and vertically is what I expect from Pdfjs-Express. Its a very high priority feature for us. Infact many of us who’s here from AutoCad. So I would expect this feature ASAP if possible. Or else a work-around for this.

Expected behaviour
User will select all those annotations which he/she wants to flip it either vertically or horizontally. Annotations should get flipped at their place.

Code snippet
A work-around would be helpful if any with code snippet.

Hey Kiran,

This is a bit of a tricky one, and unfortunately we do not have an API that does this.

To do this you need to use a transformation matrix. Fortunately, we have some utilities to help you do these matrix calculations.

  function flipAnnot(annot)  {
    const rect = annot.getRect();
    const builder = new instance.CoreControls.Math.TransformationBuilder();

    let transform = builder
      .translateTo(rect.getCenter().X, rect.getCenter().Y, 0, 0)
      .scale(-1, 1)
      .translateTo(0, 0, rect.getCenter().X, rect.getCenter().Y)

    annot.getPath().forEach(pt => pt.transform(transform));
    return annot;

This function flips the annotation horizontally. To flip it vertically, change the scale params to

.scale(1, -1)

You can use this function like so:

myFlipButton.onclick = () => {
  const annots = instance.annotManager.getSelectedAnnotations();

  annots.forEach(annot => {
    annot = flipAnnot(annot);


Hi Logan,

Thanks for this feature, but annotations aren’t getting saved by triggering annotationsChanged (modify) call. They are getting flipped but doesn’t get saved. Even though I have used -
this.viewerInstance.annotManager.trigger('annotationChanged', [[annot], 'modify', {}]);

const annots = this.viewerInstance.annotManager.getSelectedAnnotations();
annots.forEach(annot => {
annot = this.flipAnnotVertically(annot);
this.viewerInstance.annotManager.trigger(‘annotationChanged’, [[annot], ‘modify’, {}]);

I think there is some problem.


Please let us know for following issue!


I can’t reproduce your issue. The flipped annotations are getting exported correctly.

Here is the code I used to test. When button b1 is clicked, the annotation is exported, then removed, then re-added 1 second later. When it is re-added, you can see that it is flipped.

    const annots = instance.annotManager.getAnnotationsList();

    annots.forEach(annot => {
      annot = flipAnnot(annot);

    const xfdf = await instance.annotManager.exportAnnotations();


    setTimeout(() => {
    }, 1000)

Actually we have annotationChanged event -
this.viewerInstance.annotManager.on('annotationChanged', (annotations, action, {imported,isUndoRedo}) => {});

After flipping annotation, it should trigger annotationChanged event so that our all actions during export should be in sequence. Is it possible to invoke annotationChanged event for modify call after flipping?

Hey, you can manually trigger it like so

annotManager.trigger('annotationChanged', [[annot], 'modify', {}])