Pdf.js: Callback for when PDF is finished rendering?

Created on 30 Dec 2014  ·  17Comments  ·  Source: mozilla/pdf.js

I need to render a gradient to cover the bottom half of the rendered PDF. I'm working for a newspaper and we're doing an app that shows the paper with a teaser before subscribing.

The problem is, the gradient needs to be painted on top of the PDF, so it has to wait until the PDF is finished rendering. In fact, on mobile browsers attempting the gradient rendering before the PDF is finished results in extremely wild behavior (the canvas re-renders and blinks every time the page scrolls even a bit) resulting in constant re-paints and the content will render upside down sometimes.

So quite simply, I need to run a callback when the PDF has finished rendering.

Can you guys support callbacks? Or send out an event when the rendering is done?

Most helpful comment

Using the textlayerrendered event works for me:

document.addEventListener('textlayerrendered', function (e) {
  if (e.detail.pageNumber === PDFViewerApplication.page) {
    // finished rendering
  }
}, true);

All 17 comments

We have 'pagerendered' event or render() returns promise. The generic viewer never renders all pages, so this will not be fixable for the viewer, unless we introduce a mode for the PDFViewer object when it renders all pages.

Ok, so a 'pagerendered' event is fired from which object? @yurydelendik

See https://github.com/mozilla/pdf.js/blob/master/web/pdf_viewer.js#L225 and example of usage at https://github.com/mozilla/pdf.js/blob/master/web/viewer.js#L1733

Please notice that we don't have API for viewer. Only API we released is for core and canvas rendering (see src/display/api.js).

@yurydelendik I am using this with canvas, in-browser. I'm kind of confused about where else PDF JS is even relevant. That confused me right away, but anyway, it looks like you have what I'm looking for. Thanks so much!

Closing as resolved.

I'm having trouble catching this event.

I listen (Jquery) for the pagerendered event as shown in the documents above:

$(document).bind('pagerendered', function (e) {
    console.log('Page rendering complete.');
    //do stuff
});

and render the PDF on canvas:

PDFJS.getDocument('my_file.pdf').then(function(pdf) {
    pdf.getPage(1).then(function(page) {
        /* .. snip .. */
        var scaledViewport = page.getViewport(scale);
        var canvas = document.getElementById('the-canvas');
        var context = canvas.getContext('2d');
        canvas.height = scaledViewport.height;
        canvas.width = scaledViewport.width;
        var renderContext = {
            canvasContext : context,
            viewport : scaledViewport
        };
        page.render(renderContext);
});

Triggering the event myself works successfully, so my listener is set up properly, and is attached long before page.render(renderContext) is called.

Perhaps I misunderstood the event's trigger. When exactly should the pagerendered event be fired from the document?

@yurydelendik

If you are not using the generic viewer, the event will not be triggered. Sorry, I don't understood what you are asking.

See https://github.com/mozilla/pdf.js/blob/master/examples/learning/prevnext.html#L76 to see how to wait for rendering to finish. jQuery will be less useful here, try to learn how to use Promises.

@yurydelendik I understand now, thank you so much for your time!

Using the textlayerrendered event works for me:

document.addEventListener('textlayerrendered', function (e) {
  if (e.detail.pageNumber === PDFViewerApplication.page) {
    // finished rendering
  }
}, true);

Using your snippet above you'd simply do:

page.render(renderContext).then(function() {
  console.log("FINISHED RENDERING!");
}, function() {
  console.log("ERROR");
});

@brendandahl thanks )

Thank you @lucdetellis ! I have been trying to have a button external to the viewer trigger the print functionality, but it would never work due to the error given. Using your solution inside of a function allowed me to trigger that function from the parent frame and then window.focus() and window.print() when finished rendering, and BAM, issue resolved.. Was looking all over for a solution on this :)

document.addEventListener('textlayerrendered', function (e) {
  if (e.detail.pageNumber === PDFViewerApplication.page) {
    // finished rendering
  }
}, true);

Is never called for me...

I'm calling it like so (at the end viewer.js):

document.addEventListener('textlayerrendered', function (e) {
      console.log("textlayerrendered event called!");
    if (e.detail.pageNumber === PDFViewerApplication.page) {
    // finished rendering
      console.log("FINISHED RENDERING!");
      Android.makeWebViewVisible();
     } else {
     console.log("NOT DONE RENDERING!");
     }
}, true);

document.addEventListener('DOMContentLoaded', webViewerLoad, true);

Please forgive my javascript ignorance, I'm an Android developer trying to get js callbacks for when the PDF has finished rendering because I'm running into some Android specific issues... Any help would be greatly appreciated.

Updated:
The issue was that my Android WebView's visibility was not set to VISIBLE, so none of the JS events were being triggered.

Using the viewer provided with pdf.js, pagesloaded event worked for me (I open the print dialog as soon as it is finished loading):

document.addEventListener('pagesloaded', function (e) {
    window.print();
}, true);

@turquoise-turtle did you attached to event Listener to the main document or to the iframe where you have the viewer?

var iframe = document.getElementById('iframe').contentDocument;

                            iframe.addEventListener('pagesloaded', function (e) {
                                alert("loaded");
                            }, true);

i'm doing this and it doesn't seem to work

set "eventBusDispatchToDOM": true in viewer.js why isn't anyone telling this!

It seems the default was changed to not dispatch events to DOM in around August to September, looking at #10019

Was this page helpful?
0 / 5 - 0 ratings

Related issues

AlexP3 picture AlexP3  ·  3Comments

BrennanDuffey picture BrennanDuffey  ·  3Comments

anggikolo11 picture anggikolo11  ·  3Comments

jigskpatel picture jigskpatel  ·  3Comments

sujit-baniya picture sujit-baniya  ·  3Comments