RELEASE: What's New in Summer 2024
By Andrey Safonov | 2023 Jun 16
5 min
Tags
pdf viewer
react
react pdf viewer
In this blog, we will cover how to build a customizable and feature-rich PDF Viewer in React. We will be using the Apryse SDK - Apryse’s rendering engine - and building a custom UI to display PDFs, scroll pages, zoom, and search with annotation and highlighting support.
We’ll assume that you already have a Node environment setup and you have a React app up and running. If you do not, you can grab the source code to this blog on our GitHub https://github.com/PDFTron/webviewer-custom-ui. You can also just create a new React app after setting up a Node environment, by running:
npx create-react-app my-app
cd my-app
For more info on create-react-app refer to the official documentation.
Or if you prefer using Vite, then you can follow the instructions at the start of this video.
OK! Let’s get started creating our PDF rendering app!
Installing a PDF Rendering Engine
First, we need a robust rendering engine that will display PDFs. There are several open-source rendering engines available such as PDF.js and PDFium, however in this article we will use Apryse’s proprietary engine since it offers so much functionality.
Apryse’s proprietary engine comes with a lot of functionality, straight out-of-the-box. In addition to being great at rendering PDFs, it also supports:
Almost all functionality is performed directly within the browser (using WASM), making it extremely fast and keeping your documents secure rather than them being transferred over the internet and processed on a remote server.
Probably the easiest way to get the Apryse rendering engine is to run:
npm i @pdftron/webviewer
Once the package has been installed, copy the `public/core`
contents located in your `node_modules/@pdftron/webviewer/public/core`
to the `/public/webviewer`
folder in your React app.
Now, you can reference the necessary scripts for rendering between the <body> tags of `public/index.html`, similarly to how we did it in our GitHub repository for this project: https://github.com/PDFTron/webviewer-custom-ui/blob/master/public/index.html#L29
<script src="%PUBLIC_URL%/webviewer/core/webviewer-core.min.js"></script>
<script src="%PUBLIC_URL%/webviewer/core/pdf/PDFNet.js"></script>
Now, you should be able to reference it wherever you are building the PDF Viewer.
You can now create a reusable PDF Viewer component in your React app. However, in our example, we will keep things simple and just add the code directly to `App.js`.
Let’s add where the PDF will be rendered. To begin, let’s add a couple of references that we will need inside the component or App.js:
const App = () => {
const viewer = useRef(null);
const scrollView = useRef(null);
In the return method for App.js or your component, add the following:
return (
<div className="App">
<div id="scroll-view" ref={scrollView}></div>
<div id="viewer" ref={viewer}></div>
</div>
)
And then insert a `useEffect` in App.js (which should only run once upon rendering the component), and add the following:
const App = () => {
const viewer = useRef(null);
const scrollView = useRef(null);
const [documentViewer, setDocumentViewer] = useState(null);
const [annotationManager, setAnnotationManager] = useState(null);
useEffect(() => {
const Core = window.Core;
Core.setWorkerPath('/webviewer/core');
Core.enableFullPDF();
const documentViewer = new Core.DocumentViewer();
documentViewer.setScrollViewElement(scrollView.current);
documentViewer.setViewerElement(viewer.current);
documentViewer.enableAnnotations();
documentViewer.loadDocument(' https://pdftron.s3.amazonaws.com/downloads/pl/demo-annotated.pdf');
setDocumentViewer(documentViewer);
documentViewer.addEventListener('documentLoaded', () => {
setAnnotationManager(documentViewer.getAnnotationManager());
});
}, []);
Okay, what is happening there?
Provide a best-in-class viewer experience, best quality and performance across web, mobile, and desktop applications with Apryse.
Now, let’s add some CSS, to make sure the viewer looks its best. Inside of App.css (or your component’s CSS), add the following and do not forget to import it:
#scroll-view {
bottom: 0;
height: 100%;
width: 100%;
overflow: auto;
}
#viewer {
margin: auto;
}
At this point, we are ready to start our React app and see the PDF render:
npm run start
If you ran into any trouble, or something is going wrong, just refer to our GitHub sample. If you are still stuck, chat with us on Discord using the link at the end of this article.
If you are looking for a pre-built UI that is battle-tested by millions of developers, check out our other blog: https://apryse.com/blog/embed-react-pdf-viewer.
The next step, in this demo, is to allow users to draw annotations and comment on a PDF. Thanks to the Apryse Core rendering engine, WebViewer comes with out-of-the-box support for all annotation types supported in Adobe Reader. So, in this section, we are going to add a button to the UI that allows us to draw rectangles on a PDF document.
Inside the return method for App.js or your component, add the button tag just before the scroll view:
return (
<div className="App">
<button onClick={createRectangle}>Rectangle</button>
<div id="scroll-view" ref={scrollView}></div>
<div id="viewer" ref={viewer}></div>
</div>
)
Let’s now add the code that will set the tool to be a rectangle whenever that button is pressed.
Somewhere between useEffect and the return statement, add the following:
const createRectangle = () => {
documentViewer.setToolMode(documentViewer.getTool(window.Core.Tools.ToolNames.RECTANGLE));
};
Now, the button press will allow users to add rectangle annotations. Restart the app and try it yourself. We have used very basic CSS so feel free to play around with it to get it to match your overall theme.
Next Steps
At this point, you can add more tool support, page manipulation, search, redaction and more. Check out the full sample available on GitHub and refer to our guides for more information. You can also chat with us on our Discord.
This article was updated in March 2024.
PRODUCTS
Enterprise
Small Business
Popular Content