React PDF annotations — A complete overview

Table of contents

    React PDF annotations — A complete overview
    Summary

    Master React PDF annotations with this comprehensive guide to using Nutrient’s professional PDF annotation library in React applications. Learn about different annotation types — from basic markup to interactive forms — and understand the benefits of commercial solutions over building custom annotation tools. Discover how to implement both UI-based and programmatic annotations while maintaining optimal performance and user privacy.

    In this post, we’ll cover different types of PDF annotations and their potential use cases, and we’ll also show you how to implement PDF annotations in your applications using Nutrient’s React PDF annotation library with the React API.

    What are PDF annotations?

    PDF annotations are objects — like text, graphics, highlights, text boxes, etc. — that you can add to a PDF document without changing the content. They’re useful for reviewing documents, collaborating with others, and implementing interactive features such as forms.

    Normally, to annotate a document, you’d open a PDF in a third-party PDF editor and select an annotation tool.

    Drawing on a PDF

    But in place of an app, you can annotate PDF documents using frontend React code.

    This means everything is run on the client side and not on an external server. This is useful in situations where user privacy is important, since the server isn’t processing any sensitive data.

    Types of PDF annotations in React

    The PDF specification supports many types of annotations. They come in two categories:

    • Markup annotations — These are used to mark up the content of a PDF file. They’re typically used during a review process to allow your users to collaborate, emphasize parts of the text, and take notes.

    • Non-markup annotations — These are used for non-markup purposes such as adding multimedia or fillable form fields to an existing PDF.

    The following sections will provide a quick overview of the various types of PDF annotations.

    Text markup

    Text markup is used to annotate text in a PDF document. It can include highlighters, underlines, or strikeout annotations.

    Text with highlighting, underlining, and strikeout annotations

    Drawing annotations

    Drawing annotations are used to draw and write on a PDF page. You can customize the color, thickness, and transparency of the annotation tool.

    Drawing on a PDF, with the toolbar showing the annotation tool options

    Widget annotations

    Widgets are non-markup annotations. They appear in interactive forms, which include buttons, radio buttons, text fields, signature form fields, list boxes, and combo boxes. They can be used to create forms from flat documents.

    A PDF form being filled in with typed text

    Shape annotations

    These annotation types allow you to add a shape like a circle, box, or arrow annotation to a document. Cloudy annotations are commonly used in construction software to indicate a change in a plan.

    Measurement annotations

    With measurement tools, users can calculate dimensions, measure distances between lines, or trace the perimeter of drawings in a PDF document. To ensure accuracy, the scale of measurement can be changed to match the scale of the document.

    Text annotations

    This annotation type lets a user add text to a document. Users can do this by inserting a sticky note, adding a comment, or clicking and dragging a freeform text box.

    Stamp annotations

    These annotation types allow users to quickly indicate the status of a document by — for example — adding an Approved or Declined stamp. They can also be used as a call to action in a document, where a user could add a stamp for a next step, such as Needs Signature.

    Image annotations

    This type of annotation allows a user to upload and resize an image in their PDF. It can be used to quickly replace images within a document.

    You can learn more about annotation types in this blog post.

    Annotating in the UI vs. programmatically

    There are two ways to annotate PDF files: UI-based annotation and code-based annotation.

    UI annotation

    With this method, the user selects an annotation tool in a PDF viewer and modifies a file manually.

    Adding annotations in a PDF viewer

    Programmatic annotation

    With programmatic annotation, a document is annotated automatically based on predefined rules written in the code. Programmatic annotation can be performed as part of an automation workflow or during runtime when a PDF is opened, or it can be manually triggered by the user.

    Adding annotations programmatically

    This way of handling annotations is necessary for the following situations:

    • Automation workflow — Governments and banks use automation software to stamp and insert timestamps on digital documents, which makes the process quicker and more efficient.

    • User-triggered events — If a user inputs text into a text field, the PDF runs JavaScript code to verify whether the data matches a predefined format. This ensures validation is done during runtime with zero human error.

    • Customization — Some PDF programs apply personal logos and convert text into clickable links.

    Adding React PDF annotations to your solution

    There are two primary ways of adding React PDF annotation capabilities to your solution, and this next section will outline them.

    Building Your Own React PDF Annotation Solution

    One of the challenges of building your own solution is that there are currently no open source annotation libraries available. In all likelihood, you’ll need to start from scratch when building annotations into your application or software.

    It’s important to understand that PDF documents are incredibly complex file formats — the PDF specification has more than 1,000 pages(opens in a new tab). As such, you’ll need to have a general understanding of PDFs to build the logic of adding an annotation to a layer over a document at a precise point. This process typically involves deploying, testing, and continually refining the logic until it’s reasonably accurate.

    Once you’ve developed the logic, you’ll need to design the UI and icons for the annotation function in your app. This process involves first defining your toolbar layout, and then building it to account for both small and large screens.

    The last factor involves maintaining your custom annotation solution over time. We’ve heard from customers who have built their own custom annotation solution on top of PDF.js — which is an open source JavaScript library built by Mozilla — and then struggled maintaining the project. With each new release, they needed to divert developers from working on their current tasks to spending time fixing bugs.

    Commercial options for PDF annotations with React

    Since developing a document annotator can be a time-consuming endeavor, you may want to look for an out-of-the-box commercial solution. This is where Nutrient’s React PDF annotation library could be useful.

    It offers:

    • 17 annotation types, with more to come.

    • The ability to customize annotations — for example, you can change the color, shape, and size.

    • The ability to sync annotations between devices (requires server deployment).

    • Comment threads you can enable so your user can have real-time conversations in a document (requires server deployment).

    • Tooltips, which can be designed according to your needs.

    • Support for a plethora of web frameworks. This means the client doesn’t have to write APIs for multiple programming languages.

    You can view our demo to see what Nutrient is capable of and determine how you can use it for your project.

    Integrating Nutrient annotations in React

    Now that you’ve learned all about annotations, in this section, you’ll use our React API to work with annotations. Since Nutrient supports many frameworks, you can even use JavaScript or Angular, since their code samples are similar to the ones shown in this post.

    Requirements

    • At least Node version 10.0 and npm version 6. However, we recommend running your code using the latest LTS release(opens in a new tab).

    • A code editor of your choice.

    • macOS 10.10 or Windows 7, or any Linux distribution that’s currently supported.

    Project setup

    As a first step, initialize a project with npm:

    Terminal window
    npm create vite@latest react-pspdf -- --template react
    cd react-pspdf
    cd src
    mkdir components
    cd components
    touch PDFViewer.jsx # Will render your document to the client’s browser.
    cd .. # Go back to the `src` directory.

    Next, since this app will be using the pspdfkit library, install it in your project:

    Terminal window
    npm install pspdfkit

    It’s necessary to import certain styling code that will help Nutrient render your PDF to the browser:

    Terminal window
    cd .. # Navigate to the root directory.
    # Get styles and other external libraries so you can use them in your project.
    cp -R ./node_modules/pspdfkit/dist/pspdfkit-lib public/pspdfkit-lib

    When that’s done, navigate to your public directory. Here, add a PDF file of your choice for annotation purposes. You can use this demo document as an example,

    Now, create a new file within your src folder called helperFunctions.js. As the name suggests, this file will hold utility methods needed to embed annotations into your project.

    Mounting PDFs

    In this section, you’ll write the code to render a PDF to the client interface.

    Begin by adding this code to helperFunctions.js:

    async function loadPDF({ PSPDFKit, container, document }) {
    const instance = await PSPDFKit.load({
    // Container where PSPDFKit should be mounted.
    container,
    // The document to open.
    document,
    baseUrl: `${window.location.protocol}//${window.location.host}/${
    import.meta.env.BASE_URL
    }`,
    });
    return instance;
    }
    export { loadPDF }; // Export this method so you can use it in your project.
    • In this block of code, you created a function called loadPDF.

    • When React executes this function, the app will call the PSPDFKit.load method. Consequently, the library will now display the document to the UI.

    All that’s left is to use your newly created function within your app. To do so, go to PDFViewer.jsx and paste this snippet:

    import { useEffect, useRef } from "react";
    import { loadPDF } from "./helperFunctions"; // Import the `loadPDF` function.
    function PDFViewer(props) {
    const containerRef = useRef(null); // Will serve as your container to render the document.
    useEffect(() => {
    let PSPDFKit;
    const container = containerRef.current;
    (async function () {
    PSPDFKit = await import("pspdfkit");
    PSPDFKit.unload(container); // Ensure there's only one Nutrient instance.
    const instance = await loadPDF({
    // Invoke the `loadPDF` function.
    PSPDFKit,
    container,
    document: props.document, //get the document location from the prop.
    });
    })();
    // When the user closes the app, remove the PDF from RAM.
    // This prevents memory leaks.
    return () => PSPDFKit && PSPDFKit.unload(container);
    }, []);
    // Your PDF will be rendered within this PDF.
    return <div ref={containerRef} style={{ width: "100%", height: "100vh" }} />;
    }
    export default PDFViewer;

    As the last step, render the PDFViewer component to the DOM. To do so, write this snippet in your App.js file:

    import PDFViewer from "./PDFViewer";
    function App() {
    return (
    <div className="App">
    <PDFViewer document={"Document.pdf"} /> {/*Render the Document.pdf file*/}
    </div>
    );
    }
    export default App;

    Now it’s time to test it out! To run this React app, use this bash command:

    Terminal window
    npm run dev

    The final result will look like this:

    Mount PDFs React PDF Annotations

    Adding text annotations

    Nutrient uses the PSPDFKit.Annotations.TextAnnotation class for embedding text annotations.

    To use text annotations, enter the following block of code in the helperFunctions.js file:

    async function createTextAnnotation({ PSPDFKit, instance }) {
    const annotation = new PSPDFKit.Annotations.TextAnnotation({
    pageIndex: 0, // Which page number should have this annotation.
    text: {
    format: "plain",
    value: "Welcome to\nPSPDFKit",
    }, // Text to embed.
    font: "Helvetica",
    isBold: true,
    horizontalAlign: "center", // Align your annotation to the center of the box.
    boundingBox: new PSPDFKit.Geometry.Rect({
    // Position of this annotation.
    left: 50,
    top: 200,
    width: 100,
    height: 80,
    }),
    fontColor: PSPDFKit.Color.GREEN, // color of the text
    });
    // Attach this annotation to your PDF:
    const createdAnnotation = await instance.create(annotation);
    return createdAnnotation;
    }
    export { createTextAnnotation }; // Finally, export this function.

    When that’s done, all that’s left is to use your newly created helper function. To make this possible, write this line at the end of the async function in PDFViewer.js just after the loadPDF function:

    // `src/PDFViewer.jsx`
    import { createTextAnnotation } from "./helperFunctions.js";
    useEffect(() => {
    // More code.
    createTextAnnotation({ PSPDFKit, instance });
    }, []);

    This will be the result:

    Adding text annotations to a PDF

    Creating ink annotations

    To insert ink annotations, use the PSPDFKit.Annotations.InkAnnotation class. In helperFunctions.js, add the following:

    async function createInkAnnotation({ PSPDFKit, instance, x1, y1, x2, y2 }) {
    // Extract the `List`, `DrawingPoint`, `Rect`, and `InkAnnotation` properties from Nutrient.
    // These are needed to render annotations onto the screen.
    const { List } = PSPDFKit.Immutable;
    const { DrawingPoint, Rect } = PSPDFKit.Geometry;
    const { InkAnnotation } = PSPDFKit.Annotations;
    // Create your ink annotation.
    const annotation = new InkAnnotation({
    pageIndex: 0,
    boundingBox: new Rect({ width: 400, height: 100 }), //position of annotation
    strokeColor: new PSPDFKit.Color({ r: 255, b: 0, g: 255 }), //color of stroke
    lines: List([
    // Coordinates of stroke.
    List([
    new DrawingPoint({ x: x1, y: y1 }),
    new DrawingPoint({ x: x2, y: y2 }),
    ]),
    ]),
    });
    // Attach stroke to annotation:
    const createdAnnotation = await instance.create(annotation);
    return createdAnnotation;
    }
    export { createInkAnnotation };

    As the last step, run the createInkAnnotation function in the PDFViewer.jsx module:

    // `src/PDFViewer.jsx`
    useEffect(( )=> {
    // More code.
    // Draw a line from (5,5) to (100,100):
    await createInkAnnotation({
    PSPDFKit,
    instance,
    x1: 5,
    y1: 5,
    x2: 100,
    y2: 100,
    });
    }, [ ]);

    The outcome is shown below.

    Adding ink annotations to a PDF

    Exporting to XFDF

    An XFDF file(opens in a new tab) is an Adobe forms document that stores PDF-usable information. The data is written in XML.

    You can export your modified document into XFDF via the exportXFDF method within the PDFViewer.jsx module:

    useEffect(()=> {
    // More code.
    const XFDFData = await instance.exportXFDF(); // Procure XFDF data.
    console.log(XFDFData); // Log XML data to the console.
    }, [ ]);

    The result is shown below.

    XFDF version of the PDF

    Setting the annotations author

    You can set the annotation author’s name via the setAnnotationCreatorName function:

    instance.setAnnotationCreatorName("Name");

    Conclusion

    In this post, you learned all about PDF annotations, and you saw how to use Nutrient’s solutions to implement programmatic annotations in React. You can find the source code(opens in a new tab) here.

    If you want to learn more about Nutrient, you can request a free trial of our SDK, or browse our demo page to see what our API is capable of.

    FAQ

    What are PDF annotations?

    PDF annotations are elements like text, drawings, and shapes added to a PDF document to highlight or comment on content without altering the original document.

    How can I implement PDF annotations in React?

    You can use Nutrient Web SDK to add annotations to PDFs in React, either through user interactions in the UI or programmatically using the React API.

    What types of annotations can I add with Nutrient in React?

    Nutrient supports various annotations, including text markup, drawing, widgets, shapes, measurements, stamps, and images.

    How do I export annotations from a PDF to XFDF?

    You can export annotations to XFDF in React using the exportXFDF method provided by Nutrient, which captures annotations in XML format.

    Can I sync annotations across devices using Nutrient?

    Yes. Nutrient supports syncing annotations between devices, but this requires server deployment for real-time updates.

    Hussain Arif

    Hussain Arif

    Explore related topics

    FREE TRIAL Ready to get started?