2013-08-05 12 views
5

Użyłem pdf.js do stworzenia prostej przeglądarki pdf, która ma 2 strony obok siebie z następnymi, poprzednimi przyciskami i kilkoma innymi funkcjami. Użyłem przykładu helloworld dostępnego z repozytorium pdf.js, ponieważ plik viewer.js był zbyt skomplikowany dla nooba, jak ja. Jednak po kliknięciu poprzedniego/następnego przycisku kilka razy plik pdf.js renderuje wszystkie strony zamiast oczekiwanej ostatniej strony. Tworzy bałagan. Poniższy przykład pliku pdf.js ma ten sam problem. http://jsbin.com/pdfjs-prevnext-v2/1/edit (link wydaje się działać tylko w firefox).zatrzymanie renderowania strony pdf.js

Chcę się dowiedzieć, jakie są sposoby, aby pdf.js wyświetlał tylko ostatnią stronę osiągniętą przy użyciu przycisków next/previous. pdf.js api mi nie pomogło. Mam nadzieję, że otrzymam tutaj wskazówki. Z góry dziękuję.

Odpowiedz

3

Jeśli dobrze rozumiem twój problem, mogę mieć rozwiązanie. Kiedy kliknąłem zbyt szybko na przyciski poprzedniej lub następnej, płótno nie miało czasu na odświeżenie, a dwie (lub więcej) stron, na których narysowano, było nieczytelne.

Aby rozwiązać ten problem, używam następujący kod:

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); 
    } 
} 

Mam również zmodyfikowaną funkcję renderowania w pliku PDF.js:

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. 

(w moim pliku PDF.js , to jest między liniami 2563 a 2596).

W rezultacie żadna nowa strona nie zostanie narysowana, dopóki cała strona nie zostanie w całości narysowana, nawet jeśli bardzo szybko klikniesz na przyciski poprzedni/następny!

Innym rozwiązaniem mogłoby być, aby anulować poprzedni rysunek:

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; 
    }); 
} 

Mam nadzieję, że to pomoże, i przepraszam za mój angielski;) Miłego dnia

+0

Próbowałem tego i wydawało się działać lepiej niż wcześniej, jednak nadal napotyka problem podczas klikania zbyt poścą nie wiem, jeśli stoją to też. Chciałbym móc wyłączyć przyciski, dopóki płótno nie zostanie w pełni załadowane, próbowałem użyć window.onload(), nie działało, ponieważ płótno zabiera więcej czasu. Pełny plik viewer.html w pliku pdf.js ma funkcję zatrzymywania, nie może jednak ustalić, jak to zrobili. – sss

+0

Próbowałem tylko Twojego pierwszego rozwiązania, pozwól mi sprawdzić drugi. Wielkie dzięki za wysiłek i twój angielski jest świetny. :) – sss

+0

Próbowałem anulować poprzedni rysunek, jednak timestamp = pageTimestamp; Podawałem błąd, ponieważ znacznik czasu jest niezdefiniowany, więc zmieniłem kod na var timestamp = pageTimestamp; i teraz nigdy nie dostaje się do warunku if (timestamp! = pageTimestamp), ponieważ są one zawsze równe. Co ja robię źle ? Jeszcze raz dziękuję z góry. :) – sss

0

Odnośnie drugiego rozwiązania, musisz utworzyć zmienną timestamp poza funkcją, na przykład na początku pliku. Jeśli zadeklarujesz timestamp wewnątrz funkcji, zmienna istnieje tylko podczas wykonywania funkcji i nie może działać. S można wykonać następujące czynności:

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; 
    }); 
} 

Powiedz mi, czy to jest ok teraz

+0

Wielkie dzięki, działa to jak urok. Jesteś ratownikiem. Doceniam to. :) – sss

4

Mam ten sam problem i rozwiązać łatwiej. Sposób render() zwraca renderTask przedmiot, który wyglądał tak:

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

Prototyp renderTask.internalRenderTask ma cancel() metodę, która może powstrzymać renderowania. Więc po prostu pamiętać renderTask.internalRenderTask obiektu i nazywają cancel() razie potrzeby:

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

    // some code here 

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

2015: 'page.render (...)' zwraca teraz 'renderTask', który ma metodę' cancel'. -> 'this.renderTask = page.render (...);'. –