user1386893
user1386893

Reputation: 57

Responsive pdf renderer with PDFJS

I have a little problem with PDFJS and canvas.

I can display a PDF on a page, I can also display the PDF in the full width of the page (well almost, I do not know to take into account the scroll bar) but I still have a problem on resize event.

During the resize event, some pages are found upside down for no reason ...

Could you help me please ?

Thank you !

Edit : Work with replace canvas !

/*
http://code.jquery.com/jquery-3.2.1.min.js
http://mozilla.github.io/pdf.js/build/pdf.js
*/

$(function() {

  PDFJS.workerSrc = '//mozilla.github.io/pdf.js/build/pdf.worker.js';

  /* Generate scaled page's canvas */
  var generatePageCanvas = function(pdfDiv, page) {
    var canvas = document.createElement('canvas');
    var divWidth = pdfDiv.width();
    var pageWidth = page.getViewport(1).width;
    var renderContext = {
      canvasContext: canvas.getContext('2d'),
      viewport: page.getViewport(divWidth / pageWidth)
    };

    canvas.height = renderContext.viewport.height;
    canvas.width = renderContext.viewport.width;
    page.render(renderContext);

    return canvas;
  }

  /* Render a PDF's page, with resize event */
  var renderPage = function(pdfDiv, page) {
    var canvas = generatePageCanvas(pdfDiv, page);
    pdfDiv.append(canvas);

    $(window).resize(() => {
      var resizedCanvas = generatePageCanvas(pdfDiv, page);
      canvas.replaceWith(resizedCanvas);
      canvas = resizedCanvas;
    });
  };

  /* Render a PDF file */
  var renderPdf = function(pdfUrl, pdfDiv) {
    PDFJS.getDocument(pdfUrl).then(pdfDoc => {
      for (var num = 1; num <= pdfDoc.numPages; num++) {
        pdfDoc.getPage(num).then(page => {
          renderPage(pdfDiv, page);
        });
      }
    });
  };

  /* Search and render data-pdf attributes */
  $('div[data-pdf]').each(function() {
    var pdfDiv = $(this);
    var pdfUrl = pdfDiv.data('pdf');
    pdfDiv.css('overflow', 'auto')
      .css('max-height', '180px');
    renderPdf(pdfUrl, pdfDiv);
  });

  /* Simulate window resize event */
  $('button').click(function() {
    var i = 400;
    var interval = setInterval(() => {
      i += 20;
      document.body.style.width = i + "px";
      window.dispatchEvent(new Event('resize'));
    }, 250);
    setTimeout(() => {
      clearInterval(interval);
    }, 1000);
  });

});
<html>
  <head>
    <script src="//mozilla.github.io/pdf.js/build/pdf.js"></script>
    <script src="//code.jquery.com/jquery-3.2.1.min.js"></script>
  </head>

  <body>

    <button>
      Simulate resize
    </button>
    <div data-pdf="//cdn.mozilla.net/pdfjs/tracemonkey.pdf"></div>
    <div data-pdf="//cdn.mozilla.net/pdfjs/helloworld.pdf"></div>

  </body>
</html>

Upvotes: 2

Views: 5573

Answers (1)

alainschaller
alainschaller

Reputation: 113

It is an old post but as I came across this same subject lately, I found a solution to update the pdfviewer to new dimensions like after a resize of the container in which the viewer is rendered.

The documentation of the lib being somewhat limited, I found a solution by going across the source code and found the following piece of code (pdf.js/web/app.js@webViewerResize: lines 2449-2464 on github):

function webViewerResize() {
  const { pdfDocument, pdfViewer } = PDFViewerApplication;
  if (!pdfDocument) {
    return;
  }
  const currentScaleValue = pdfViewer.currentScaleValue;
  if (
    currentScaleValue === "auto" ||
    currentScaleValue === "page-fit" ||
    currentScaleValue === "page-width"
  ) {
    // Note: the scale is constant for 'page-actual'.
    pdfViewer.currentScaleValue = currentScaleValue;
  }
  pdfViewer.update();
}

By applying the same sequence in my callback made the viewer “resize” accordingly to my configured currentScaleValue.

This feels to work a bit "automagically" as I didn't take the time to go deeper into the source code. Therefore, feel free to add any details to the reason why this works.


Disclamer: "tested" with version 2.9.359 of pdfjs-dist

Upvotes: 1

Related Questions