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

问题描述 投票:23回答:10

我正在使用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事件。

html5 canvas pdf.js
10个回答
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
};

0
投票

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

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

17
投票

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

为我工作


14
投票

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

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

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

5
投票

使用textlayerrendered事件为我工作:

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

4
投票

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

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

3
投票

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

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

});

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

希望这可以帮助。干杯!


1
投票

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

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

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


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

});

希望有所帮助。


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);
});
© www.soinside.com 2019 - 2024. All rights reserved.