如何知道PDF.JS是否已完成渲染?

时间:2012-10-02 15:17:06

标签: html5 canvas pdf.js

我正在使用PDF.JS将pdf页面渲染到不同的画布元素中。我的要求是捕获画布的输出并将其显示为图像。是否有一些事件要知道画布中的pdf页面的渲染是否已经完成。因为当我尝试捕获画布的输出时,它是空白的。但pdf页面正确呈现。 看起来我的捕获事件在pdf.js完成渲染过程之前被调用。

这是我的代码:

page.render(renderContext);
var myImage = new Image();
myImage.src = document.getElementById('my-canvas-id').toDataURL();
$('body').append(myImage);

如果我在FireFox控制台中执行相同的代码,这样可以正常工作。所以这段代码没什么问题。

只是为了让你们知道我已经尝试过document.ready和window.load活动。

14 个答案:

答案 0 :(得分:21)

我也在努力解决这个问题..我使用的解决方案是:

//Step 1: store a refer to the renderer
var pageRendering = page.render(renderContext);
//Step : hook into the pdf render complete event
var completeCallback = pageRendering.internalRenderTask.callback;
pageRendering.internalRenderTask.callback = function (error) {
  //Step 2: what you want to do before calling the complete method                  
  completeCallback.call(this, error);
  //Step 3: do some more stuff
};

答案 1 :(得分:17)

<script type="text/javascript">
  document.addEventListener("pagesloaded", function(e) {
   //do sth..
  });
</script>

为我工作

答案 2 :(得分:12)

  

在撰写本文时,这确实有效。我不确定它是否仍然存在。

PDFJS使用Promises。最简单的方法是:

page.render(renderContext).promise.then(function(){
  document.body.appendChild(canvas);
});

答案 3 :(得分:5)

使用textlayerrendered事件为我工作:

document.addEventListener('textlayerrendered', function (event) {
  // was this the last page?
  if (event.detail.pageNumber === PDFViewerApplication.page) {
    console.log('Finished rendering!');
  }
}, true);

答案 4 :(得分:4)

里昂的解决方案更加强大。但这是我能找到的最简单的解决方案。

var renderTask = pdfPage.render(renderContext);
renderTask.promise.then(
  function pdfPageRenderCallback() {
    pageViewDrawCallback(null);
  },
  function pdfPageRenderError(error) {
    pageViewDrawCallback(error);
  }
);

答案 5 :(得分:3)

在检查这些解决方案时,我遇到问题renderContext,所以我最终使用这种方法听取pagerendered

document.addEventListener("pagerendered", function(e){

});

在我的情况下,我只是想在页面渲染后调用一些外部函数,只需要很少的努力。

希望这会有所帮助。干杯!

答案 6 :(得分:2)

根据来自 PDF.js 的文档。

对于 2.2 之前的版本使用:
page.render(renderContext).then(function(){
var myImage = new Image();
myImage.src = document.getElementById('my-canvas-id').toDataURL();
$('body').append(myImage);
});

对于 2.2 之后的版本,请使用: page.render(renderContext).promise.then(function(){
var myImage = new Image();
myImage.src = document.getElementById('my-canvas-id').toDataURL();
$('body').append(myImage);
});

答案 7 :(得分:1)

我已经用这种方式改变了我的代码,它帮助了我想做的事情:

pageRendering = page.render(renderContext);
pageRendering.onData(function(){
    var myImage = new Image();
    myImage.src = document.getElementById('my-canvas-id').toDataURL();
    $('body').append(myImage);
});

仅当特定页面已完成渲染时才有用。它没有告诉你所有页面的渲染。

答案 8 :(得分:1)

事实证明,您的第一行page.render(renderContext);会返回一个RenderTask对象,该对象有3个属性:

  • internalRenderTask - InternalRenderTask,duh
  • 取消 - 一个功能,可能是为了让您取消渲染工作
  • 承诺 - jQuery Promise对象

承诺是你想要的。为了使用它,它是这样的:

  

page.render(renderContext) .promise .then(function(){

//do something after the page is rendered here
     

});

希望有所帮助。

答案 9 :(得分:1)

根据使用的PDF.js组件(和版本),还可以使用EventBus。

如果使用的是最简单的PDF.js实现,则可能无法使用,但是如果使用的是SimpleViewer or PageViewer examples,请尝试以下操作:

        eventBus.on("pagesloaded", function() {
            console.log('pagesloaded');
            // your code here
        });

eventBus应该已经定义好了,否则,您可以使用以下命令进行设置:

var eventBus = new pdfjsViewer.EventBus();

同样,这取决于PDF Viewer的复杂程度。事实证明,PDF.js中有许多不同的层。

要监听每个页面加载,请使用eventBus事件'pagerendered'

答案 10 :(得分:1)

如果您在查看器应用程序中使用 pdf.js,这是我发现等待它初始化的最佳方法:

// Wait for the PDFViewerApplication to initialize                                                                                                                         
PDFViewerApplication.initializedPromise.then(function() {
    // Do whatever startup code you need to here, now that the EventBus
    // is read. For example:
    PDFViewerApplication.eventBus.on('pagerendered', function (e) {
        annotationInterface.onPageRendered(e);
    });
});

答案 11 :(得分:0)

如果你想在不同的画布中渲染pdf文档的所有页面,所有这些页面都是同步的,这是一种解决方案:

的index.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>PDF Sample</title>
    <script type="text/javascript" src="jquery.js"></script>
    <script type="text/javascript" src="pdf.js"></script>
    <script type="text/javascript" src="main.js">
    </script>
    <link rel="stylesheet" type="text/css" href="main.css">
</head>
<body id="body">  
</body>
</html>

的main.css

canvas {
    display: block;
}

main.js

$(function() {  
    var filePath = "document.pdf";

    function Num(num) {
        var num = num;

        return function () {
            return num;
        }
    };

    function renderPDF(url, canvasContainer, options) {
        var options = options || {
                scale: 1.5
            },          
            func,
            pdfDoc,
            def = $.Deferred(),
            promise = $.Deferred().resolve().promise(),         
            width, 
            height,
            makeRunner = function(func, args) {
                return function() {
                    return func.call(null, args);
                };
            };

        function renderPage(num) {          
            var def = $.Deferred(),
                currPageNum = new Num(num);
            pdfDoc.getPage(currPageNum()).then(function(page) {
                var viewport = page.getViewport(options.scale);
                var canvas = document.createElement('canvas');
                var ctx = canvas.getContext('2d');
                var renderContext = {
                    canvasContext: ctx,
                    viewport: viewport
                };

                if(currPageNum() === 1) {                   
                    height = viewport.height;
                    width = viewport.width;
                }

                canvas.height = height;
                canvas.width = width;

                canvasContainer.appendChild(canvas);

                page.render(renderContext).then(function() {                                        
                    def.resolve();
                });
            })

            return def.promise();
        }

        function renderPages(data) {
            pdfDoc = data;

            var pagesCount = pdfDoc.numPages;
            for (var i = 1; i <= pagesCount; i++) { 
                func = renderPage;
                promise = promise.then(makeRunner(func, i));
            }
        }

        PDFJS.disableWorker = true;
        PDFJS.getDocument(url).then(renderPages);       
    };

    var body = document.getElementById("body");
    renderPDF(filePath, body);
});

答案 12 :(得分:0)

page.render是一个承诺,所以你必须在你的成功中做你喜欢的事情,如下所示:

page.render({
  canvasContext: context,
  viewport: viewport
}).then(function() {
//do your stuff here });

答案 13 :(得分:0)

window.addEventListener('load', function () {
    PDFViewerApplication.eventBus.on('textlayerrendered', function () {
      console.log('textlayerrendered', arguments, PDFViewerApplication)
    })

事件名称textlayerrendered包括PDFViewerApplication.eventBus._listeners