PDF.js
is a JavaScript library maintained by Mozilla and designed for handling PDFs in JavaScript.
We are going to create a PDF viewer that has the following functionalities:
Create an index.html
file that includes:
<canvas id="pdf_canvas"></canvas>
<div>
<button id="prev_page">Previos Page</button>
<button id="next_page">next Page</button>
<span id="current_page_num"></span>
of
<span id="total_page_num"></span>
<input type="text" id="page_num">
<button id="go_to_page">Go To Page</button>
</div>
<script src="//mozilla.github.io/pdf.js/build/pdf.js"></script>
<script src="script.js" charset="utf-8"></script>
In addition to the index.html
file, we will create a script.js
file where we can write our JavaScript code to create a PDF viewer.
let pdf ; // to store pdf data
let canvas; // to render pdf
let isPageRendering; // to check if the pdf is currently rendering
let pageRenderingQueue = null; // to store next page number to render
let canvasContext; // context of canvas
let totalPages; // total pages of pdf
let currentPageNum = 1;
Next, add event listeners to handle the PDF renderer once the page loads:
window.addEventListener('load', function () {
isPageRendering= false;
pageRenderingQueue = null;
canvas = document.getElementById('pdf_canvas');
canvasContext = canvas.getContext('2d');
initEvents(); Add events
initPDFRenderer(); // render first page
});
initPDFRenderer
functiongetPage
functiongetPage
will return a promise
resolved
, we get the page data
render
method in the page data to render it in the canvasfunction initPDFRenderer() {
let url = 'https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf';
// const url = 'filepath.pdf'; // to load pdf from our machine
let option = { url};
pdfjsLib.getDocument(option)
.promise
.then( pdfData => {
totalPages = pdfData.numPages; // total number of pages
let pagesCounter= document.getElementById('total_page_num'); // update total pages text
pagesCounter.textContent = totalPages;
// assigning read pdfContent to global variable
pdf = pdfData;
console.log(pdfData);
renderPage(currentPageNum);
});
}
Now, when we call initPdfRenderer
it will assign the pdfData to the PDF variable.
Add events for previousButton
, nextButton
, and goToPage
buttons.
function initEvents() {
let prevPageBtn = document.getElementById('prev_page');
let nextPageBtn = document.getElementById('next_page');
let goToPage = document.getElementById('go_to_page');
prevPageBtn.addEventListener('click', renderPreviousPage);
nextPageBtn.addEventListener('click',renderNextPage);
goToPage.addEventListener('click', goToPageNum);
}
renderPage
functionNow, let’s create a renderPage
function to render the PDF page to the canvas.
function renderPage(pageNumToRender = 1) {
isPageRendering = true;
document.getElementById('current_page_num').textContent = pageNumToRender;
// use getPage method
pdf
.getPage(pageNumToRender)
.then( page => {
const viewport = page.getViewport({scale :1});
canvas.height = viewport.height;
canvas.width = viewport.width;
let renderCtx = {canvasContext ,viewport};
page
.render(renderCtx)
.promise
.then(()=> {
isPageRendering = false;
// this is to check if there is next page to be rendered in the queue
if(pageRenderingQueue !== null) {
renderPage(pageRenderingQueue);
pageRenderingQueue = null;
}
});
});
}
We have a method to get pdfData and render the page. Let’s write our pageRenderingQueue
.
If the user clicks next page/previous page, it will add/subtract 1 to the currentPageNum and pass it to the renderPageQueue
method. This will check if the pageRenderingQueue
is null. If it is null, then we call the renderPage
method, or else it will assign the page number that is to be rendered to the queue
. Once the page rendering is complete, it will check if the pageQueue
is empty and perform the respective action (if needed).
function renderPageQueue(pageNum) {
if(pageRenderingQueue != null) {
pageRenderingQueue = pageNum;
} else {
renderPage(pageNum);
}
}
Let’s create a renderNextPage
and renderPreviousPage
method.
If the user clicks:
next page
– currentPageNum + 1
and render page.previous page
– currentPageNum — 1
and render page.function renderNextPage(ev) {
if(currentPageNum >= totalPages) {
alert("This is the last page");
return ;
}
currentPageNum++;
renderPageQueue(currentPageNum);
}
function renderPreviousPage(ev) {
if(currentPageNum<=1) {
alert("This is the first page");
return ;
}
currentPageNum--;
renderPageQueue(currentPageNum);
}
Now, let’s implement the “go to page number” function.
Get the page number from the input box, then check if the number is valid and call the renderPage method.
function goToPageNum(ev) {
let numberInput = document.getElementById('page_num');
let pageNumber = parseInt(numberInput.value);
if(pageNumber) {
if(pageNumber <= totalPages && pageNumber >= 1){
currentPageNum = pageNumber;
numberInput.value ="";
renderPageQueue(pageNumber);
return ;
}
}
alert("Enter a valide page numer");
}