Advertisement
  1. Web Design
  2. HTML/CSS
  3. HTML

Cómo crear un visor de PDF en JavaScript

Scroll to top
Read Time: 9 min

() translation by (you can also view the original English article)

El formato de documento portátil, o PDF para abreviar, es ideal para compartir documentos que contengan gran cantidad de texto e imágenes con formato preciso, especialmente si es probable que sean impresos o leídos sin conexión. Si bien la mayoría de los navegadores modernos pueden mostrar archivos PDF, estos lo hacen usando un visor PDF que se ejecuta en una pestaña o ventana independiente, lo que forza a los usuarios a abandonar tu sitio web.

PDF.js es una biblioteca de JavaScript de código abierto que te permite analizar y desplegar archivos PDF directamente desde el interior de tus páginas web. En este tutorial te mostraré cómo usarla para crear un completo visor de PDF personalizado desde cero.

1. Creando una interfaz de usuario

Vamos a comenzar creando una nueva página web y añadiéndole el código HTML5 habitual.

1
<!doctype html>
2
3
<html lang="en">
4
<head>
5
  <meta charset="utf-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1">
7
  <title>My PDF Viewer</title>
8
</head>
9
<body>
10
    
11
</body>
12
</html>

A continuación, dentro de <body>, crea un elemento <div> que pueda servir como contenedor para nuestro visor de PDF.

1
<div id="my_pdf_viewer">
2
    
3
</div>

En el corazón de nuestro visor de PDF se encontrará un elemento <canvas> de HTML5. Vamos a desplegar las páginas de nuestros archivos PDF en su interior. Por lo tanto, agrega el siguiente código dentro del elemento <div>.

1
<div id="canvas_container">
2
    <canvas id="pdf_renderer"></canvas>
3
</div>

Para simplificar las cosas, vamos a mostrar solamente una página dentro del elemento canvas en cualquier momento dado. Sin embargo, permitiremos que los usuarios vayan a la página anterior o a la siguiente presionando un botón. Además, para mostrar el número de la página actual, y para permitir a los usuarios que vayan a cualquier página que deseen, nuestra interfaz deberá tener un campo de entrada.

1
<div id="navigation_controls">
2
    <button id="go_previous">Previous</button>
3
    <input id="current_page" value="1" type="number"/>
4
    <button id="go_next">Next</button>
5
</div>

Para permitir operaciones de acercamiento y alejamiento, agrega otros dos botones a la interfaz: uno para acercar y uno para alejar.

1
<div id="zoom_controls">  
2
    <button id="zoom_in">+</button>
3
    <button id="zoom_out">-</button>
4
</div>

2. Obteniendo PDF.js

Ahora que está lista la estructura de la interfaz de usuario para nuestro visor de PDF, agreguemos PDF.js a nuestra página web. Ya que la versión más reciente de la biblioteca está disponible en CDNJS, podemos hacerlo simplemente agregando las siguientes líneas al final de la página web.

1
<script

2
    src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.0.943/pdf.min.js">
3
</script>

Si prefieres usar una copia local de la biblioteca, puedes descargarla desde el repositorio pdfjs-dist.

3. Cargando un archivo PDF

Antes de que comencemos a cargar un archivo PDF, vamos a crear un objeto simple de JavaScript para almacenar el estado de nuestro visor de PDF. En su interior debemos tener tres elementos: una referencia al archivo PDF en sí, el índice de la página actual y el nivel de acercamiento actual.

1
<script>
2
    var myState = {
3
        pdf: null,
4
        currentPage: 1,
5
        zoom: 1
6
    }
7
8
    // more code here

9
</script>

En este punto podemos cargar nuestro archivo PDF invocando al método getDocument() del objeto pdfjsLib, que se ejecuta de forma asíncrona.

1
pdfjsLib.getDocument('./my_document.pdf').then((pdf) => {
2
3
    // more code here

4
5
});

Nota que el método getDocument() usa un objeto XMLHttpRequest internamente para cargar el archivo PDF. Esto significa que el archivo debe estar presente ya sea en tu propio servidor web o en un servidor que permita solicitudes de origen cruzado.

Si no tienes un archivo PDF a la mano, puedes obtener el que estoy usando aquí.

Una vez que el archivo PDF haya sido cargado correctamente, podemos actualizar la propiedad pdf de nuestro objeto de estado.

1
myState.pdf = pdf;

Por último, agrega una llamada a una función de nombre render() para que nuestro visor de PDF despliegue automáticamente la primera página del archivo PDF. Definiremos la función en el siguiente paso.

1
render();

4. Desplegando una página

Al invocar al método getPage() del objeto pdf y enviarle un número de página, podemos obtener una referencia a cualquier página del interior del archivo PDF. Por ahora vamos a enviarle la propiedad currentPage de nuestro objeto de estado. Este método también devuelve una promesa, así que necesitaremos una función de devolución de llamada para gestionar su resultado.

De acuerdo a esto, crea una nueva función llamada render() que contenga el siguiente código:

1
function render() {
2
    myState.pdf.getPage(myState.currentPage).then((page) => {
3
4
        // more code here

5
6
    });
7
}

Para desplegar una página, debemos invocar al método render() del objeto page disponible dentro de la devolución de llamada. Como argumentos, el método espera el contexto 2D de nuestro elemento canvas y un objeto PageViewport, que podemos obtener invocando al método getViewport(). Ya que el método getViewport() espera el nivel de acercamiento deseado como argumento, debemos enviarle la propiedad zoom de nuestro objeto de estado.

1
var canvas = document.getElementById("pdf_renderer");
2
var ctx = canvas.getContext('2d');
3
4
var viewport = page.getViewport(myState.zoom);

Las dimensiones del viewport dependen del tamaño original de la página y del nivel de acercamiento. Para garantizar que todo el viewport sea mostrado en nuestro elemento canvas, ahora debemos cambiar el tamaño de este último para que se ajuste al tamaño del viewport. Esta es la forma de hacerlo:

1
canvas.width = viewport.width;
2
canvas.height = viewport.height;

En este punto podemos ir y mostrar la página.

1
page.render({
2
    canvasContext: ctx,
3
    viewport: viewport
4
});

Si intentas abrir la página web en un navegador, ahora podrás ver la primera página de tu archivo PDF.

PDF viewer displaying the first page of a PDF filePDF viewer displaying the first page of a PDF filePDF viewer displaying the first page of a PDF file

Quizá hayas notado que el tamaño de nuestro visor de PDF actualmente depende del tamaño de la página mostrada y del nivel de acercamiento. Esto no es ideal, ya que no queremos que el diseño de nuestra página web se vea afectado mientras los usuarios interactúan con el visor de PDF. Para solucionar esto, lo único que tenemos que hacer es asignarle un ancho y una altura fijos al elemento <div> que está encapsulando a nuestro elemento canvas y configurar su propiedad overflow de CSS con el valor auto. Cuando es necesario, esta propiedad agrega barras de desplazamiento al elemento <div>, permitiendo a los usuarios moverse tanto horizontal como verticalmente.

Agrega el siguiente código dentro de la etiqueta <head> de la página web:

1
<style>
2
    #canvas_container {
3
        width: 800px;
4
        height: 450px;
5
        overflow: auto;
6
    }
7
</style>

Desde luego, tienes la libertad de cambiar el ancho y la altura o incluso usar consultas de medios para lograr que el elemento <div> se ajuste a tus requisitos.

De manera opcional, puedes incluir las siguientes reglas de CSS para que el elemento <div> sea más distinguible:

1
#canvas_container {
2
    background: #333;
3
    text-align: center;
4
    border: solid 3px;
5
}

Si actualizas la página web ahora, deberás ver algo como esto en tu pantalla.

PDF viewer displaying first page of a PDF file with scrollPDF viewer displaying first page of a PDF file with scrollPDF viewer displaying first page of a PDF file with scroll

5. Cambiando la página actual

Nuestro visor PDF actualmente es capaz de mostrar solamente la primera página de cualquier archivo PDF dado. Para permitir a los usuarios cambiar la página mostrada, ahora debemos añadir agentes de escucha de eventos click a los botones go_previous y go_next que creamos anteriormente.

Dentro del agente de escucha de eventos del botón go_previous debemos disminuir la propiedad currentPage de nuestro objeto de estado, asegurándonos de que no sea menor a 1. Después de que hagamos esto, simplemente podemos invocar a la función render() de nuevo para mostrar la nueva página.

Además, debemos actualizar el valor del campo de texto current_page, para que muestre el nuevo número de página. El siguiente código te muestra cómo:

1
document.getElementById('go_previous')
2
        .addEventListener('click', (e) => {
3
            if(myState.pdf == null
4
               || myState.currentPage == 1) return;
5
            myState.currentPage -= 1;
6
            document.getElementById("current_page")
7
                    .value = myState.currentPage;
8
            render();
9
        });

De manera similar, dentro del agente de escucha de eventos del botón go_next, debemos incrementar la propiedad currentPage y asegurarnos de que no exceda el número de páginas presentes en el archivo PDF, lo cuál podemos determinar usando la propiedad numPages del objeto _pdfInfo.

1
document.getElementById('go_next')
2
        .addEventListener('click', (e) => {
3
            if(myState.pdf == null 
4
               || myState.currentPage > myState.pdf
5
                                               ._pdfInfo.numPages) 
6
               return;
7
        
8
            myState.currentPage += 1;
9
            document.getElementById("current_page")
10
                    .value = myState.currentPage;
11
            render();
12
        });

Finalmente, debemos añadir un agente de escucha de eventos de pulsación de teclas al campo de texto current_page, para que los usuarios puedan saltar directamente a cualquier página que deseen simplemente escribiendo un número de página y presionando la tecla Enter. Dentro del agente de escucha de eventos, necesitamos asegurarnos de que el número que el usuario haya escrito sea mayor a cero y menor o igual a la propiedad numPages.

1
document.getElementById('current_page')
2
        .addEventListener('keypress', (e) => {
3
            if(myState.pdf == null) return;
4
        
5
            // Get key code

6
            var code = (e.keyCode ? e.keyCode : e.which);
7
        
8
            // If key code matches that of the Enter key

9
            if(code == 13) {
10
                var desiredPage = 
11
                        document.getElementById('current_page')
12
                                .valueAsNumber;
13
                                
14
                if(desiredPage >= 1 
15
                   && desiredPage <= myState.pdf
16
                                            ._pdfInfo.numPages) {
17
                        myState.currentPage = desiredPage;
18
                        document.getElementById("current_page")
19
                                .value = desiredPage;
20
                        render();
21
                }
22
            }
23
        });

Ahora nuestro visor de PDF puede mostrar cualquier página del archivo PDF.

PDF viewer displaying page 3 of the PDF filePDF viewer displaying page 3 of the PDF filePDF viewer displaying page 3 of the PDF file

6. Cambiando el nivel de acercamiento

Ya que nuestra función render() ya usa la propiedad zoom del objeto de estado al desplegar una página, ajustar el nivel de acercamiento es tan sencillo como incrementar o disminuir el valor de la propiedad e invocar a la función.

Dentro del agente de escucha de eventos on-click del botón zoom_in, vamos a incrementar la propiedad zoom en 0.5.

1
document.getElementById('zoom_in')
2
        .addEventListener('click', (e) => {
3
            if(myState.pdf == null) return;
4
            myState.zoom += 0.5;
5
            render();
6
        });

Y dentro del agente de escucha de eventos on-click del botón zoom_out, vamos a disminuir la propiedad zoom en 0.5.

1
document.getElementById('zoom_out')
2
        .addEventListener('click', (e) => {
3
            if(myState.pdf == null) return;
4
            myState.zoom -= 0.5;
5
            render();
6
        });

Tienes la libertad de añadir un límite superior e inferior a la propiedad zoom, pero no son necesarios.

Nuestro visor de PDF está listo. Si actualizas la página web de nuevo, podrás ver todas las páginas presentes en el archivo PDF y también hacer acercamientos o alejamientos en ellas.

PDF viewer displaying a page at a high zoom levelPDF viewer displaying a page at a high zoom levelPDF viewer displaying a page at a high zoom level

Conclusión

Ahora sabes cómo usar PDF.js para crear un visor PDF personalizado para tu sitio web. Con él, puedes ofrecer con confianza una experiencia de usuario sin complicaciones al mostrar los folletos, libros blancos, formularios y otros documentos de tu organización que generalmente están destinados a ser distribuidos como copias impresas.

Puedes aprender más acerca de PDF.js en el repositorio oficial de GitHub.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Web Design tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.