StaticFast

How to create a PDF viewer in JavaScript

The PDF.js JavaScript library renders Portable Document Format files using the web standards-compliant HTML5 Canvas, which is led by the Mozilla Corporation after Andreas Gal launched it in 2011. Many PDF documents support interactive fields such as text boxes, checkboxes, and radio buttons to allow users to fill in data before downloading a filled-out copy of the file to their computer. Some PDFs also support annotations, which are notes and highlights drawn on a document that can be saved and shared with others.

In this tutorial, we will show you how to create a PDF viewer using PDF.js. We will be using Tailwind CSS to style the page. Tailwind CSS makes inline style super easy and we highly recommend it.

Include the PDF.js Library and Tailwind CSS Asset

Firstly, let's create an HTML template named "index.html":

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>PDF Viewer</title> </head> <body> </body> </html>

Nothing special above, it is just a plain HTML skeleton.

In the header section of the page, include PDF.js and Tailwind CSS from their respective CDN.

Tailwind CSS is hosted on its CDN:

PDF.js is hosted on three free CDN:

Include them respectively before the closing header tag:

<head> ... <script src="https://cdn.tailwindcss.com"></script> <script src="https://cdn.jsdelivr.net/npm/pdfjs-dist@2.0.943/build/pdf.min.js"></script> ... </head>

Work on The Design of The Viewer

Let's design the PDF viewer using Tailwind CSS's utility classes:

<div id="pdf-viewer" class="max-w-5xl mx-auto flex flex-col gap-4 items-center justify-center py-10"> <div id="canvas-container" class="space-y-4"> <div class="flex w-full items-center justify-between"> <div id="nav" class="flex items-center justify-start gap-2"> <button id="prev" class="py-2 px-3 bg-indigo-600 hover:bg-indigo-200 text-white transition delay-150 duration-300 ease-in-out"> &#8592 </button> <span id="current">1</span> <button id="next" class="py-2 px-3 bg-indigo-600 hover:bg-indigo-200 text-white transition delay-150 duration-300 ease-in-out"> &#8594 </button> </div> <div class="flex items-center justify-end gap-2"> <button id="zoom-in" class="rounded-full py-1 px-3 bg-indigo-600 hover:bg-indigo-200 text-white transition delay-150 duration-300 ease-in-out"> &#43; </button> <button id="zoom-out" class="rounded-full py-1 px-3 bg-indigo-600 hover:bg-indigo-200 text-white transition delay-150 duration-300 ease-in-out"> &#45; </button> </div> </div> <canvas id="pdf-renderer" class="border"></canvas> </div> </div>

Paste the HTML code to the body section of the page, you should get something similar to the page below:

page-1.jpg

There are a couple of elements to take note:

Work on the PDF Functions

Render the PDF Viewer

Now we have built the look and feel of the PDF viewer. The first function we are going to implement is to render the PDF file to the viewer.

Before the closing body tag, paste the code below:

<script> var myState = { pdf: null, currentPage: 1, zoom: 1 } pdfjsLib.getDocument('./sample.pdf').then((pdf) => { myState.pdf = pdf; render(); }); function render() { myState.pdf.getPage(myState.currentPage).then((page) => { var canvas = document.getElementById('pdf-renderer'); var ctx = canvas.getContext('2d'); var viewport = page.getViewport(myState.zoom); canvas.width = viewport.width; canvas.height = viewport.height; page.render({ canvasContext: ctx, viewport: viewport }); }); } </script> </body> </html>

The myState variable stores the current state of our PDF viewer including the actual PDF.js object, current viewing page, and zoom level.

We then use pdfjsLib.getDocument to load the local PDF via a promise.

The function function render() figures which page of the PDF file to render with respective size and render it in the pdf-renderer canvas element.

Implement the Page Controls

If we open the viewer on the browser now, we will notice that only a single page is rendered and we are not able to navigate through the PDF file.

Time to implement the page controls, paste the code below after the code previous section:

document.getElementById('prev') .addEventListener('click', (e) => { if (myState.pdf == null || myState.currentPage == 1) return; myState.currentPage -= 1; document.getElementById('current').textContent = myState.currentPage; render(); }); document.getElementById('next') .addEventListener('click', (e) => { if(myState.pdf == null || myState.currentPage > myState.pdf._pdfInfo.numPages) return; myState.currentPage += 1; document.getElementById('current').textContent = myState.currentPage; render(); });

The code above figures the correct page to render and call the render() function to complete the task.

Implement the Zoom Controls

Currently, if we try to view the PDF file, the words might be a bit blurry due to the zoom level. We need to implement the zoom controls to make sure everyone can view the PDF content. Paste the code below after the code previous section:

document.getElementById('zoom-in') .addEventListener('click', (e) => { if(myState.pdf == null) return; myState.zoom += 0.5; render(); }); document.getElementById('zoom-out') .addEventListener('click', (e) => { if(myState.pdf == null) return; myState.zoom -= 0.5; render(); });

The code above figures the correct zoom level to render and call the render() function to complete the task.

The End

Now our PDF viewer should be working nicely with its page control as well as zoom controls:

page-2.jpg

© 2024 StaticMaker. All rights reserved.