How to Add Annotations to a PDF Using React Native
In this post, you’ll learn how to use React Native to add annotations to PDF documents.
PSPDFKit lets you easily add document annotation functionality to your React Native application. This tutorial will explore how to add ink and text annotations, how to set an annotation author, and how to embed annotations into PDFs.
PSPDFKit React Native PDF Library
PSPDFKit offers a commercial React Native PDF library for viewing, generating, annotating, and editing PDFs. You can use it to quickly add PDF functionality to your React Native applications.
It offers a variety of additional features and capabilities, including:
-
15+ out-of-the-box annotations to mark up, draw on, and add comments to documents.
-
PDF editing to merge, split, rotate, and crop documents.
-
PDF forms to create, fill, and capture PDF form data.
-
Digital signatures to validate the authenticity and integrity of a PDF.
Requirements
For this tutorial, you’ll need a React Native development environment for running React Native projects using the React Native command-line interface (CLI) — not the Expo CLI — and configured for the platforms you want to build (Android, iOS, or both).
Dependencies
There are two dependencies you’ll need:
Getting Started
Here’s an overview of the steps you’ll follow:
Installing the Necessary Dependencies
-
Create a fresh React Native project:
npx react-native init PSPDFKitAnnotations
-
Change to the project directory and add the PSPDFKit plugin:
cd PSPDFKitAnnotations
yarn add react-native-pspdfkit@github:PSPDFKit/react-native
The PSPDFKit React Native dependency is installed from the GitHub repository and not the npm registry. To install the PSPDFKit React Native dependency, run
yarn add react-native-pspdfkit@github:PSPDFKit/react-native
in your project directory ornpm install github:PSPDFKit/react-native
if you’re using npm.
-
Add the react-native-fs dependency:
yarn add react-native-fs
-
Now, install all the dependencies for the project:
yarn install
-
Open your project’s
android/build.gradle
file and add the PSPDFKit repository to download the PSPDFKit library:
... allprojects { repositories { mavenLocal() + maven { + url 'https://my.nutrient.io/maven/' + } ... 6. Open your project’s `ios/Podfile` in a text editor to update the platform to iOS 14, and add the PSPDFKit Podspec: ```diff require_relative '../node_modules/react-native/scripts/react_native_pods' require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' - platform :ios, '11.0' + platform :ios, '14.0' target 'PSPDFKitDemo' do config = use_native_modules! use_react_native!( :path => config[:reactNativePath], # To enable Hermes on iOS, change `false` to `true` and then install pods. :hermes_enabled => false ) target 'PSPDFKitDemoTests' do inherit! :complete # Pods for testing end + pod 'PSPDFKit', podspec: 'https://my.pspdfkit.com/pspdfkit-ios/latest.podspec' # Enables Flipper. # # Note that if you have `use_frameworks!` enabled, Flipper won't work and # you should disable the next line. use_flipper!() post_install do |installer| react_native_post_install(installer) end end
-
For PSPDFKit for iOS SDK version 12.1.0 and above, it’s necessary to set the license key in the
AppDelegate
object before initializing PSPDFKit for the first time. Open theios/PSPDFKitAnnotations/AppDelegate.mm
file and add the following:// Add the import statement. #import <PSPDFKit/PSPDFKit.h> @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Set the license key. Use an empty string when using a trial version. [PSPDFKitGlobal setLicenseKey:@""];
-
Change to the
ios
directory and install the CocoaPods dependencies:cd ios
pod install
-
Open your project’s Workspace in Xcode:
open PSPDFKitDemo.xcworkspace
-
Make sure the deployment target is set to 14.0 or higher.
-
Change
View controller-based status bar appearance
toYES
in your project’sInfo.plist
.
Displaying a PDF Document
-
Add the PDF document you want to display to your application by dragging it into your project. In the dialogue that’s displayed, select Finish to accept the default integration options. You can use this Quickstart Guide PDF as an example.
-
Change to the root of your project and create the
assets
directory:cd ..
mkdir android/app/src/main/assets
-
Then, copy the PDF document you want to display to the
assets
directory. -
Open the
App.js
file and delete all its contents. Then, add the following import statements:import React, { Component } from 'react'; import { Platform, NativeModules } from 'react-native'; import PSPDFKitView from 'react-native-pspdfkit';
-
Point to the document you added earlier:
const DOCUMENT = Platform.OS === 'ios' ? 'Document.pdf' : 'file:///android_asset/Document.pdf';
-
Now, display the document with the
PSPDFKitView
component:<PSPDFKitView document={DOCUMENT} configuration={{ showThumbnailBar: 'scrollable', pageTransition: 'scrollContinuous', scrollDirection: 'vertical', }} ref={pdfRef} fragmentTag="PDF1" style={{ flex: 1 }} />
-
Put it all together:
import React, { Component } from 'react'; import { Platform, NativeModules } from 'react-native'; import PSPDFKitView from 'react-native-pspdfkit'; const PSPDFKit = NativeModules.PSPDFKit; PSPDFKit.setLicenseKey(null); const DOCUMENT = Platform.OS === 'ios' ? 'Document.pdf' : 'file:///android_asset/Document.pdf'; export default class PSPDFKitDemo extends Component { constructor(props) { super(props); this.pdfRef = React.createRef(); } render() { var pdfRef: React.RefObject<PSPDFKitView> = React.createRef(); return ( <PSPDFKitView document={DOCUMENT} configuration={{ showThumbnailBar: 'scrollable', pageTransition: 'scrollContinuous', scrollDirection: 'vertical', }} ref={pdfRef} fragmentTag="PDF1" style={{ flex: 1 }} /> ); } }
-
Open your terminal and launch your application:
npx react-native run-android
```bash npx react-native run-ios ```
Creating Ink Annotations
-
PSPDFKit for React Native leverages Instant JSON to import and export annotations. The PDF changes, such as annotations, can be stored in a separate JSON file with Instant JSON and added as an overlay to the existing PDF. You’ll use the following JSON for this example:
const annotationJSONInk = { bbox: [ 89.586334228515625, 98.5791015625, 143.12948608398438, 207.1583251953125, ], isDrawnNaturally: false, lineWidth: 5, lines: { intensities: [ [0.5, 0.5, 0.5], [0.5, 0.5, 0.5], ], points: [ [ [92.086334228515625, 101.07916259765625], [92.086334228515625, 202.15826416015625], [138.12950134277344, 303.2374267578125], ], [ [184.17266845703125, 101.07916259765625], [184.17266845703125, 202.15826416015625], [230.2158203125, 303.2374267578125], ], ], }, opacity: 1, pageIndex: 0, name: 'A167811E-6D10-4546-A147-B7AD775FE8AC', strokeColor: '#DC143C', type: 'pspdfkit/ink', v: 1, };
The
bbox
array contains the size and positional data for the annotation’s bounding box.
-
You can add ink annotations to your document by passing the above JSON to the
addAnnotation(jsonAnnotation)
function. Create aButton
component, which will trigger theaddAnnotation
function when pressed:
<Button onPress={() => { const annotationJSONInk = { bbox: [ 89.586334228515625, 98.5791015625, 143.12948608398438, 207.1583251953125, ], isDrawnNaturally: false, lineWidth: 5, lines: { intensities: [ [0.5, 0.5, 0.5], [0.5, 0.5, 0.5], ], points: [ [ [92.086334228515625, 101.07916259765625], [92.086334228515625, 202.15826416015625], [138.12950134277344, 303.2374267578125], ], [ [184.17266845703125, 101.07916259765625], [184.17266845703125, 202.15826416015625], [230.2158203125, 303.2374267578125], ], ], }, opacity: 1, pageIndex: 0, name: 'A167811E-6D10-4546-A147-B7AD775FE8AC', strokeColor: '#DC143C', type: 'pspdfkit/ink', v: 1, }; this.pdfRef.current .addAnnotation(annotationJSONInk) .then((result) => { if (result) { alert('Annotation was successfully added.'); } else { alert('Failed to add annotation.'); } }) .catch((error) => { alert(JSON.stringify(error)); }); }} title="Add Ink Annotation" accessibilityLabel="Add Ink Annotation" />
-
Put it all together:
import React, { Component } from 'react'; import { Platform, Button, NativeModules } from 'react-native'; import PSPDFKitView from 'react-native-pspdfkit'; const PSPDFKit = NativeModules.PSPDFKit; PSPDFKit.setLicenseKey(null); const DOCUMENT = Platform.OS === 'ios' ? 'Document.pdf' : 'file:///android_asset/Document.pdf'; export default class PSPDFKitDemo extends Component { constructor(props) { super(props); this.pdfRef = React.createRef(); } render() { var pdfRef: React.RefObject<PSPDFKitView> = React.createRef(); return ( <> <PSPDFKitView document={DOCUMENT} configuration={{ showThumbnailBar: 'scrollable', pageTransition: 'scrollContinuous', scrollDirection: 'vertical', }} ref={pdfRef} fragmentTag="PDF1" style={{ flex: 1 }} /> <Button onPress={() => { const annotationJSONInk = { bbox: [ 89.586334228515625, 98.5791015625, 143.12948608398438, 207.1583251953125, ], isDrawnNaturally: false, lineWidth: 5, lines: { intensities: [ [0.5, 0.5, 0.5], [0.5, 0.5, 0.5], ], points: [ [ [92.086334228515625, 101.07916259765625], [92.086334228515625, 202.15826416015625], [138.12950134277344, 303.2374267578125], ], [ [184.17266845703125, 101.07916259765625], [184.17266845703125, 202.15826416015625], [230.2158203125, 303.2374267578125], ], ], }, opacity: 1, pageIndex: 0, name: 'A167811E-6D10-4546-A147-B7AD775FE8AC', strokeColor: '#DC143C', type: 'pspdfkit/ink', v: 1, }; this.pdfRef.current .addAnnotation(annotationJSONInk) .then((result) => { if (result) { alert('Annotation was successfully added.'); } else { alert('Failed to add annotation.'); } }) .catch((error) => { alert(JSON.stringify(error)); }); }} title="Add Ink Annotation" accessibilityLabel="Add Ink Annotation" /> </> ); } }
Replace the contents of
App.js
with the above for a working example.
-
Launch the app:
npx react-native run-android
npx react-native run-ios
Adding Text Annotations
-
Similar to ink annotations, you’ll define the text annotation JSON first:
const annotationJSONText = { bbox: [ 89.586334228515625, 98.5791015625, 143.12948608398438, 207.1583251953125, ], horizontalAlign: 'center', verticalAlign: 'center', isBold: true, text: 'Welcome to\nPSPDFKit', font: 'Helvetica', fontColor: '#DC143C', fontSize: 24.0, opacity: 1, pageIndex: 0, name: 'A167811E-6D10-4546-A147-B7AD775FE8AC', type: 'pspdfkit/text', v: 1, };
-
Create a
Button
component, which will trigger theaddAnnotation(jsonAnnotation)
function when pressed:
<Button onPress={() => { const annotationJSONText = { bbox: [ 89.586334228515625, 98.5791015625, 143.12948608398438, 207.1583251953125, ], horizontalAlign: 'center', verticalAlign: 'center', isBold: true, text: 'Welcome to\nPSPDFKit', font: 'Helvetica', fontColor: '#DC143C', fontSize: 24.0, opacity: 1, pageIndex: 0, name: 'A167811E-6D10-4546-A147-B7AD775FE8AC', type: 'pspdfkit/text', v: 1, }; this.pdfRef.current .addAnnotation(annotationJSONText) .then((result) => { if (result) { alert('Annotation was successfully added.'); } else { alert('Failed to add annotation.'); } }) .catch((error) => { alert(JSON.stringify(error)); }); }} title="Add Text Annotation" accessibilityLabel="Add Text Annotation" />
-
In your
App.js
file, you’ll have:
import React, { Component } from 'react'; import { Platform, Button, NativeModules } from 'react-native'; import PSPDFKitView from 'react-native-pspdfkit'; const PSPDFKit = NativeModules.PSPDFKit; PSPDFKit.setLicenseKey(null); const DOCUMENT = Platform.OS === 'ios' ? 'Document.pdf' : 'file:///android_asset/Document.pdf'; export default class PSPDFKitDemo extends Component { constructor(props) { super(props); this.pdfRef = React.createRef(); } render() { return ( <> <PSPDFKitView document={DOCUMENT} configuration={{ showThumbnailBar: 'scrollable', pageTransition: 'scrollContinuous', scrollDirection: 'vertical', }} ref={this.pdfRef} fragmentTag="PDF1" style={{ flex: 1 }} /> <Button onPress={() => { const annotationJSONInk = { bbox: [ 89.586334228515625, 98.5791015625, 143.12948608398438, 207.1583251953125, ], isDrawnNaturally: false, lineWidth: 5, lines: { intensities: [ [0.5, 0.5, 0.5], [0.5, 0.5, 0.5], ], points: [ [ [92.086334228515625, 101.07916259765625], [92.086334228515625, 202.15826416015625], [138.12950134277344, 303.2374267578125], ], [ [184.17266845703125, 101.07916259765625], [184.17266845703125, 202.15826416015625], [230.2158203125, 303.2374267578125], ], ], }, opacity: 1, pageIndex: 0, name: 'A167811E-6D10-4546-A147-B7AD775FE8AC', strokeColor: '#DC143C', type: 'pspdfkit/ink', v: 1, }; this.pdfRef.current .addAnnotation(annotationJSONInk) .then((result) => { if (result) { alert('Annotation was successfully added.'); } else { alert('Failed to add annotation.'); } }) .catch((error) => { alert(JSON.stringify(error)); }); }} title="Add Ink Annotation" accessibilityLabel="Add Ink Annotation" /> <Button onPress={() => { const annotationJSONText = { bbox: [ 89.586334228515625, 98.5791015625, 143.12948608398438, 207.1583251953125, ], horizontalAlign: 'center', verticalAlign: 'center', isBold: true, text: 'Welcome to\nPSPDFKit', font: 'Helvetica', fontColor: '#DC143C', fontSize: 24.0, opacity: 1, pageIndex: 0, name: 'A167811E-6D10-4546-A147-B7AD775FE8AC', type: 'pspdfkit/text', v: 1, }; this.pdfRef.current .addAnnotation(annotationJSONText) .then((result) => { if (result) { alert('Annotation was successfully added.'); } else { alert('Failed to add annotation.'); } }) .catch((error) => { alert(JSON.stringify(error)); }); }} title="Add Text Annotation" accessibilityLabel="Add Text Annotation" /> </> ); } }
Replace the contents of
App.js
with the above for a working example.
-
Launch your app:
npx react-native run-android
npx react-native run-ios
Setting an Annotation Author
Programmatically adding an author name is accomplished by passing the annotationAuthorName
prop in the PSPDFKitView
component:
<PSPDFKitView document={DOCUMENT} + annotationAuthorName={'Jane Appleseed'} configuration={{ showThumbnailBar: 'scrollable', pageTransition: 'scrollContinuous', scrollDirection: 'vertical', }} ref={this.pdfRef} fragmentTag="PDF1" style={{flex: 1}} />
Embedding Annotations into a PDF
Before creating a new document with embedded annotations, it’s necessary to save all the annotations in the current document first. This can be done by calling the saveCurrentDocument()
function.
After a successful save, call the PSPDFKit.processAnnotations(annotationChange, annotationType, sourceDocumentPath, processedDocumentPath)
function to create a new document with embedded annotations.
Once again, you’ll create a Button
component, which will trigger the above steps. Don’t forget to import the react-native-fs
and NativeModules
before continuing:
import React, {Component} from 'react'; - import {Platform, Button} from 'react-native'; + import {Platform, Button, NativeModules} from 'react-native'; import PSPDFKitView from 'react-native-pspdfkit'; + import RNFS from 'react-native-fs'; const DOCUMENT = Platform.OS === 'ios' ? 'Document.pdf' : 'file:///android_asset/Document.pdf'; + const {PSPDFKit} = NativeModules; + PSPDFKit.setLicenseKey(null); ...
<Button onPress={async () => { const processedDocumentPath = RNFS.DocumentDirectoryPath + '/flattened.pdf'; // Delete the processed document if it already exists. RNFS.exists(processedDocumentPath) .then((exists) => { if (exists) { RNFS.unlink(processedDocumentPath); } }) .then(() => { // First, save all annotations in the current document. this.pdfRef.current .saveCurrentDocument() .then((success) => { if (success) { console.log(PSPDFKit); // Then, embed all the annotations. PSPDFKit.processAnnotations( 'embed', 'all', DOCUMENT, processedDocumentPath, ) .then((success) => { if (success) { // And finally, present the newly processed document with embedded annotations. PSPDFKit.present( processedDocumentPath, {}, ); } else { alert('Failed to embed annotations.'); } }) .catch((error) => { alert(JSON.stringify(error)); }); } else { alert('Failed to save current document.'); } }); }); }} title="Embed All Annotations" />
You’ll have the following in your App.js
:
import React, { Component } from 'react'; import { Platform, Button, NativeModules } from 'react-native'; import PSPDFKitView from 'react-native-pspdfkit'; import RNFS from 'react-native-fs'; const DOCUMENT = Platform.OS === 'ios' ? 'Document.pdf' : 'file:///android_asset/Document.pdf'; const { PSPDFKit } = NativeModules; PSPDFKit.setLicenseKey(null); export default class PSPDFKitDemo extends Component { constructor(props) { super(props); this.pdfRef = React.createRef(); } render() { return ( <> <PSPDFKitView document={DOCUMENT} annotationAuthorName={'Jane Appleseed'} configuration={{ showThumbnailBar: 'scrollable', pageTransition: 'scrollContinuous', scrollDirection: 'vertical', }} ref={this.pdfRef} fragmentTag="PDF1" style={{ flex: 1 }} /> <Button onPress={() => { const annotationJSONInk = { bbox: [ 89.586334228515625, 98.5791015625, 143.12948608398438, 207.1583251953125, ], isDrawnNaturally: false, lineWidth: 5, lines: { intensities: [ [0.5, 0.5, 0.5], [0.5, 0.5, 0.5], ], points: [ [ [92.086334228515625, 101.07916259765625], [92.086334228515625, 202.15826416015625], [138.12950134277344, 303.2374267578125], ], [ [184.17266845703125, 101.07916259765625], [184.17266845703125, 202.15826416015625], [230.2158203125, 303.2374267578125], ], ], }, opacity: 1, pageIndex: 0, name: 'A167811E-6D10-4546-A147-B7AD775FE8AC', strokeColor: '#DC143C', type: 'pspdfkit/ink', v: 1, }; this.pdfRef.current .addAnnotation(annotationJSONInk) .then((result) => { if (result) { alert('Annotation was successfully added.'); } else { alert('Failed to add annotation.'); } }) .catch((error) => { alert(JSON.stringify(error)); }); }} title="Add Ink Annotation" accessibilityLabel="Add Ink Annotation" /> <Button onPress={() => { const annotationJSONText = { bbox: [ 89.586334228515625, 98.5791015625, 143.12948608398438, 207.1583251953125, ], horizontalAlign: 'center', verticalAlign: 'center', isBold: true, text: 'Welcome to\nPSPDFKit', font: 'Helvetica', fontColor: '#DC143C', fontSize: 24.0, opacity: 1, pageIndex: 0, name: 'A167811E-6D10-4546-A147-B7AD775FE8AC', type: 'pspdfkit/text', v: 1, }; this.pdfRef.current .addAnnotation(annotationJSONText) .then((result) => { if (result) { alert('Annotation was successfully added.'); } else { alert('Failed to add annotation.'); } }) .catch((error) => { alert(JSON.stringify(error)); }); }} title="Add Text Annotation" accessibilityLabel="Add Text Annotation" /> <Button onPress={async () => { const processedDocumentPath = RNFS.DocumentDirectoryPath + '/flattened.pdf'; // Delete the processed document if it already exists. RNFS.exists(processedDocumentPath) .then((exists) => { if (exists) { RNFS.unlink(processedDocumentPath); } }) .then(() => { // First, save all annotations in the current document. this.pdfRef.current .saveCurrentDocument() .then((success) => { if (success) { // Then, embed all the annotations. PSPDFKit.processAnnotations( 'embed', 'all', DOCUMENT, processedDocumentPath, ) .then((success) => { if (success) { // And finally, present the newly processed document with embedded annotations. PSPDFKit.present( processedDocumentPath, {}, ); } else { alert( 'Failed to embed annotations.', ); } }) .catch((error) => { alert(JSON.stringify(error)); }); } else { alert( 'Failed to save current document.', ); } }); }); }} title="Embed All Annotations" /> </> ); } }
Replace the contents of
App.js
with the above for a working example.
Launch your app:
npx react-native run-android
npx react-native run-ios
Conclusion
In this post, you learned how to annotate PDFs and embed annotations into a PDF in React Native using PSPDFKit. In case of any hiccups, don’t hesitate to reach out to our Support team for help.
PSPDFKit for React Native is an SDK for viewing, annotating, and editing PDFs. It offers developers the ability to quickly add PDF functionality to any React Native application. Try it for free, or visit our demo to see it in action.
FAQ
How can I add annotations to a PDF in React Native?
You can add annotations using the PSPDFKitView
component, which allows you to display and modify PDF documents.
What types of annotations can I add using PSPDFKit in React Native?
You can add various types of annotations like ink, text, and more using PSPDFKit’s React Native PDF library.
Does PSPDFKit support both iOS and Android for React Native applications?
Yes, PSPDFKit supports both iOS and Android in React Native applications.
Can I embed annotations directly into the PDF file?
Yes, annotations can be embedded into the PDF file using the provided functionality in PSPDFKit.
Do I need a license key to use PSPDFKit in React Native?
Yes, you need a PSPDFKit license key, though you can use an empty string during the trial period.