Domanda

I have used pdf.js to create a simple pdf viewer that has 2 pages side by side with next,previous buttons and some other features. I used the helloworld example available with the pdf.js repo as the viewer.js file was too complicated for a noob like me. However when I click the previous/next button several times pdf.js renders all the pages instead of the expected last page. It creates a mess. The following example by pdf.js have the same problem. http://jsbin.com/pdfjs-prevnext-v2/1/edit (link seems to work in firefox only.)

I want to know what are the ways to make pdf.js render only the last page reached by next/previous buttons. pdf.js api did not help me much. Hope I will get some guidance here. Thanks in advance.

È stato utile?

Soluzione 2

If I understand well your problem, I might have a solution. When I clicked too fast on the buttons previous or next, the canvas had not the time to refresh, and two (or more) pages where drawn, it was unreadable.

To solve the problem, I use the following code :

var stop = false;
function goPrevious() {
    if (pageNum > 1 && !stop)
    {
        stop = true;
        pageNum--;
        renderPage(pageNum);
    }
}

function goNext() {
    if (pageNum < pdfDoc.numPages && !stop)
    {
        stop = true;
        pageNum++;
        renderPage(pageNum);
    }
}

I have also modified the render function in the pdf.js file :

 render: function PDFPageProxy_render(params) {
      this.renderInProgress = true;

      var promise = new Promise();
      var stats = this.stats;
      stats.time('Overall');
      // If there is no displayReadyPromise yet, then the operatorList was never
      // requested before. Make the request and create the promise.
      if (!this.displayReadyPromise) {
        this.displayReadyPromise = new Promise();
        this.destroyed = false;

        this.stats.time('Page Request');
        this.transport.messageHandler.send('RenderPageRequest', {
          pageIndex: this.pageNumber - 1
        });
      }

      var self = this;
      function complete(error) {
        self.renderInProgress = false;
        stop = false;
        if (self.destroyed || self.cleanupAfterRender) {
          delete self.displayReadyPromise;
          delete self.operatorList;
          self.objs.clear();
        }

        if (error)
          promise.reject(error);
        else
          promise.resolve();
      }
      var continueCallback = params.continueCallback;
//etc.

(in my pdf.js file, this is between lines 2563 and 2596).

As a result, no new page will be drawn until the previous page was entirely drawn, even if you click very very fast on the previous/next buttons !

An other solution could be to cancel the previous drawing :

function renderPage(num) {


pdfDoc.getPage(num).then(function(page) {

        // canvas resize
        viewport = page.getViewport(ratio);
        canvas.height = viewport.height;
        canvas.width = viewport.width;


        // draw the page into the canvas
        var pageTimestamp = new Date().getTime();
        timestamp = pageTimestamp;
        var renderContext = {
                canvasContext: ctx,
                viewport: viewport,
                continueCallback: function(cont) {
                    if(timestamp != pageTimestamp) {
                        return;
                    }
                    cont();
                }
        };
        page.render(renderContext);


        // update page numbers
        document.getElementById('page_num').textContent = pageNum;
        document.getElementById('page_count').textContent = pdfDoc.numPages;
    });
}

I hope it will help you, and sorry for my english ;) Have a nice day

Altri suggerimenti

I have the same problem and solve it easier. The render() method returns a renderTask object which look like this:

renderTask: {
    internarRenedrTask: {...},
    promise: {...}
}

The prototype of renderTask.internalRenderTask has cancel() method which can halt rendering. So just remember renderTask.internalRenderTask object and call cancel() if needed:

render: function() {
    if (this.renderTask) {
        this.renderTask.cancel();
    }

    // some code here

    this.renderTask = page.render(...).internalRenderTask;
}

Concerning the second solution, you have to create the variable timestamp outside the function, for example at the beginning of the file. If you declare timestamp inside the function, the variable exists only during the execution of the function and it can't work. S you can do the following :

var timestamp;
function renderPage(num) {


pdfDoc.getPage(num).then(function(page) {

        // canvas resize
        viewport = page.getViewport(ratio);
        canvas.height = viewport.height;
        canvas.width = viewport.width;


        // draw the page into the canvas
        var pageTimestamp = new Date().getTime();
        timestamp = pageTimestamp;
        var renderContext = {
                canvasContext: ctx,
                viewport: viewport,
                continueCallback: function(cont) {
                    if(timestamp != pageTimestamp) {
                        return;
                    }
                    cont();
                }
        };
        page.render(renderContext);


        // update page numbers
        document.getElementById('page_num').textContent = pageNum;
        document.getElementById('page_count').textContent = pdfDoc.numPages;
    });
}

Tell me if it's ok now

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top