Búsqueda de sitios web

twitter bootstrap - PDF.JS ¿Cómo hacer que el visor de pdf-js sea responsivo en el canvas?


Tengo que mostrar un PDF usando la biblioteca PDFJS en mi página. El problema es que, dado que doy la escala como un número fijo, el lienzo en el que se renderiza el PDF no es responsivo y no se ajusta al ancho de la columna de la cuadrícula de Bootstrap. Aquí está el código HTML:

<div class="row">
   <div class="col-md-1" style="padding-right: 15px;">
     <input type="button" ng-click="openPreviousPage()"/>
   </div>
   <div class="col-md-8">
     <canvas id="the-canvas" style="border: 1px solid black;"></canvas>
    </div>
    <div class="col-md-1 col-md-offset-2" style="padding-right:15px;">
      <input type="button" ng-click="openNextPage()" />
    </div>
</div>

y mi Typescript en un controlador:

 openPage = (pdf: PDFDocumentProxy, pageNumber: number) => {
        pdf.getPage(pageNumber).then(function getPage(page) {
            var scale = 1;
            var viewport = page.getViewport(scale);

            var canvas = <HTMLCanvasElement>document.getElementById('the-canvas');
            var context = canvas.getContext('2d');
            canvas.height = viewport.height;
            canvas.width = viewport.width;


            var renderContext = {
                canvasContext: context,
                viewport: viewport
            };

            //...rest of actions
        });
    }

Agradecería cualquier pista.

Respuesta #1

Puedes poner un id en el contenedor div del lienzo y establecer la escala basándote en div.clientWidth y viewport.width.

En tu código HTML:

<div class="row">
  <div class="col-md-1" style="padding-right: 15px;">
    <input type="button" ng-click="openPreviousPage()"/>
  </div>
  <div class="col-md-8" id="the-container">
    <canvas id="the-canvas" style="border: 1px solid black;"></canvas>
  </div>
  <div class="col-md-1 col-md-offset-2" style="padding-right:15px;">
    <input type="button" ng-click="openNextPage()" />
  </div>
</div>

Luego en el controlador:

openPage = (pdf: PDFDocumentProxy, pageNumber: number) => {
    pdf.getPage(pageNumber).then(function getPage(page) {
        var container = document.getElementById('the-container');
        var canvas = <HTMLCanvasElement>document.getElementById('the-canvas');
        var context = canvas.getContext('2d');

        var viewport = page.getViewport(1);
        var scale = container.clientWidth / viewport.width;
        viewport = page.getViewport(scale);

        canvas.height = viewport.height;
        canvas.width = viewport.width;


        var renderContext = {
            canvasContext: context,
            viewport: viewport
        };

        //...rest of actions
    });
}

Espero que esto ayude...

Respuesta #2

Para cualquiera que esté trabajando a partir del ejemplo de Acroforms como punto de partida, puede notar que viewport.width no coincide con lo que se está mostrando en la pantalla al inspeccionar, lo que hace que la solución anterior renderice el PDF más grande de lo deseado. En mi caso, viewport.width era 612, pero se estaba renderizando a 816. Finalmente descubrí que esto es resultado de la variable CSS_UNITS que se encuentra dentro de pdf_viewer.js. Una vez que lo descubrí, afiné mi búsqueda en Google y encontré la conversación que discute su propósito:

"En el mundo de html/css 1in=96 píxeles, en PDF el valor predeterminado es 1in=72 píxeles. La escala se usa para que al mostrar un PDF al 100%, un PDF de 8.5in debería mostrarse en la pantalla como 8.5in."

Para ajustar esta variable, que no es global, simplemente la declaré nuevamente localmente y luego ajusté la fórmula de escala arriba para incluirla, así:

    'use strict';

    PDFJS.workerSrc = '/assets/plugins/PDFjs/web/test/pdf.worker.js';

    var DEFAULT_URL = '/assets/plugins/PDFjs/web/test/form.pdf';
    var DEFAULT_SCALE = 1.0;
    var CSS_UNITS = 96/72;
    var container = document.getElementById('pageContainer');

    // Fetch the PDF document from the URL using promises.
    PDFJS.getDocument(DEFAULT_URL).then(function (doc) {

      // Use a promise to fetch and render the next page.
      var promise = Promise.resolve();
      for (var i = 1; i <= doc.numPages; i++) {
          promise = promise.then(function (pageNum) {
            return doc.getPage(pageNum).then(function (pdfPage) {

                var viewport = pdfPage.getViewport(DEFAULT_SCALE);
                var scale = container.clientWidth / (viewport.width * CSS_UNITS);

                // Create the page view.
                var pdfPageView = new PDFJS.PDFPageView({
                  container: container,
                  id: pageNum,
                  scale: scale,
                  defaultViewport: pdfPage.getViewport(scale),
                  annotationLayerFactory: new PDFJS.DefaultAnnotationLayerFactory(),
                  renderInteractiveForms: true,
                });

            // Associate the actual page with the view and draw it.
            pdfPageView.setPdfPage(pdfPage);
            return pdfPageView.draw();
          });
        }.bind(null, i));
      }
    });

Ahora me funciona bien. Espero haber podido ahorrarles algo de tiempo a alguno de ustedes. :)

¡Salud!

Artículos relacionados