How to Create a JavaScript PDF Viewer

Difficulty:IntermediateLength:MediumLanguages:

The Portable Document Format, or PDF for short, is ideal for sharing documents containing lots of precisely formatted text and images, especially if they're likely to be printed or read offline. Although most modern browsers can display PDF files, they do so using a PDF viewer that runs in an independent tab or window, forcing users to leave your website.

PDF.js is an open-source JavaScript library that allows you to parse and render PDF files right inside your web pages. In this tutorial, I'll show you how to use it to create a fully fledged custom JavaScript PDF viewer from scratch.

If you're adding a PDF viewer to your site, you might also be interested in a professional Flipbook plugin. JavaScript flipbooks showcase your content in a digital flipbook form, using page-flipping effects, zoom, and support for multiple content types.

1. Creating a User Interface

Let's start by creating a new web page and adding the usual HTML5 boilerplate code to it.

Next, inside the <body>, create a <div> element that can serve as a container for our PDF viewer.

At the heart of our JavaScript PDF viewer will be an HTML5 <canvas> element. We'll be rendering the pages of our PDF files inside it. So add the following code inside the <div> element.

To keep things simple, we'll be rendering only one page inside the canvas at any given time. We will, however, allow users to switch to the previous page or the next page by pressing a button. Additionally, to display the current page number, and to allow users to jump to any page they desire, our interface will have an input field.

To support zoom operations, add two more buttons to the interface: one to zoom in and one to zoom out.

At the end of this section, the web page code looks like this.

2. Getting PDF.js

Now that a bare-bones user interface for our JavaScript PDF viewer is ready, let's add PDF.js to our web page. Because the latest version of the library is available on CDNJS, we can do so by simply adding the following lines towards the end of the web page.

If you prefer to use a local copy of the library, you can download it from the pdfjs-dist repository.

Before we start loading a PDF file, let's create a simple JavaScript object to store the state of our PDF viewer. Inside it, we'll have three items: a reference to the PDF file itself, the current page index, and the current zoom level.

At this point, we can load our PDF file by calling the getDocument() method of the pdfjsLib object, which runs asynchronously.

Note that the getDocument() method internally uses an XMLHttpRequest object to load the PDF file. This means that the file must be present either on your own web server or on a server that allows cross-origin requests.

If you don't have a PDF file handy, you can get the one I'm using from Wikipedia.

Once the PDF file has been loaded successfully, we can update the pdf property of our state object.

Lastly, add a call to a function named render() so that our PDF viewer automatically renders the first page of the PDF file. We'll define the function in the next step.

4. Rendering a Page

By calling the getPage() method of the pdf object and passing a page number to it, we can get a reference to any page inside the PDF file. For now, let's pass the currentPage property of our state object to it. This method too returns a promise, so we'll need a callback function to handle its result.

Accordingly, create a new function called render() containing the following code:

To actually render a page, we must call the render() method of the page object available inside the callback. As arguments, the method expects the 2D context of our canvas and a PageViewport object, which we can get by calling the getViewport() method. Because the getViewport() method expects the desired zoom level as an argument, we must pass the zoom property of our state object to it.

The dimensions of the viewport depend on the original size of the page and the zoom level. In order to make sure that the entire viewport is rendered on our canvas, we must now change the size of our canvas to match that of the viewport. Here's how:

At this point, we can go ahead and render the page.

Putting it all together, the whole source code looks like this.

If you try opening the web page in a browser, you should now be able to see the first page of your PDF file.

You may have noticed that the size of our PDF viewer currently depends on the size of the page being rendered and the zoom level. This is not ideal because we don't want the layout of our web page to be affected while users interact with the PDF viewer.

To fix this, all we need to do is give a fixed width and height to the <div> element encapsulating our canvas and set its overflow CSS property to auto. This property, when necessary, adds scroll bars to the <div> element, allowing users to scroll both horizontally and vertically.

Add the following code inside the <head> tag of the web page:

You are, of course, free to change the width and height or even use media queries to make the <div> element match your requirements.

Optionally, you can include the following CSS rules to make the <div> element seem more distinct:

If you refresh the web page now, you should see something like this on your screen:

5. Changing the Current Page

Our JavaScript PDF viewer is currently capable of showing only the first page of any PDF file given to it. To allow users to change the page being rendered, we must now add click event listeners to the go_previous and go_next buttons we created earlier.

Inside the event listener of the go_previous button, we must decrement the currentPage property of our state object, making sure that it doesn't fall below 1. After we do so, we can simply call the render() function again to render the new page.

Additionally, we must update the value of the current_page text field so that it displays the new page number. The following code shows you how:

Similarly, inside the event listener of the go_next button, we must increment the currentPage property while ensuring that it doesn't exceed the number of pages present in the PDF file, which we can determine using the numPages property of the _pdfInfo object.

Lastly, we must add a key press event listener to the current_page text field so that users can directly jump to any page they desire by simply typing in a page number and hitting the Enter key. Inside the event listener, we need to make sure that the number the user has entered is both greater than zero and less than or equal to the numPages property.

Our PDF viewer can now display any page of the PDF file.

6. Changing the Zoom Level

Because our render() function already uses the zoom property of the state object while rendering a page, adjusting the zoom level is as easy as incrementing or decrementing the property and calling the function.

Inside the on-click event listener of the zoom_in button, let's increment the zoom property by 0.5.

And inside the on-click event listener of the zoom_out button, let's decrement the zoom property by 0.5.

You are free to add upper and lower bounds to the zoom property, but they are not required.

This is what it looks like when it's put all together.

Our PDF viewer is ready. If you refresh the web page again, you should be able to view all the pages present in the PDF file and also zoom in to or zoom out of them.

Conclusion

You now know how to use PDF.js to create a custom JavaScript PDF viewer for your website. With it, you can confidently offer a seamless user experience while displaying your organization's brochures, white papers, forms, and other documents generally meant to be distributed as hard copies.

You might also be interested in a professional flipbook plugin. JavaScript flipbooks showcase your content in a digital flipbook form, using page-flipping effects, zoom, and support for multiple content types. CodeCanyon is a marketplace for all kinds of code, including premium JavaScript widgets and jQuery plugins. It's the best place to find jQuery flipbook plugins.