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?
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
Most helpful comment
Using the
textlayerrendered
event works for me: