如何修复此错误无法在多个 render() 操作期间使用相同的画布

问题描述 投票:0回答:7

我在 React 中使用画布,并使用画布将 pdf 渲染为图像。

现在,当我获得新数据,即添加另一个 pdf 时,然后 再次必须使用画布。

我不确定如何修复此错误或如何删除画布,甚至在再次使用画布之前清除画布。

相关代码如下:

 pdfLoop = (item,index) => {
        var that = this;
        PDFJS.getDocument(item).then(function getPdfHelloWorld(pdf) {
             //
             // Fetch the first page
             console.log('url is : ',item);
             pdf.getPage(1).then(function getPageHelloWorld(page) {
               var scale = 0.5;
               var viewport = page.getViewport(scale);


                   let cref = 'canvas'+index;
                   let imgref ='img'+index;
                   console.log('cref no : ',cref);
                   console.log('img no : ',imgref);

                   // Prepare canvas using PDF page dimensions
                   //
                   var canvas = that.canvasRefs[cref];
                   //let imagez = that.imageRefs[imgref];
                   var context = canvas.getContext('2d');
                   context.globalcompositeoperation = 'source-over';
                  // context.fillStyle = "#fff";
                  //draw on entire canvas
                  //context.fillRect( 0, 0, canvas.width, canvas.height );
                   canvas.height = viewport.height;
                   canvas.width = viewport.width;

                    //imagez.src = canvas.toDataURL("image/png");
                   //
                   // Render PDF page into canvas context
                   //
                   //page.render({canvasContext: context, viewport: viewport});
                   var task = page.render({canvasContext: context, viewport: viewport})
              task.promise.then(function(){
                //console.log(canvas.toDataURL('image/png'));
                let imgItem = {imgref:canvas.toDataURL('image/png'),page:index+1,rotate:0}

                 let newState = that.state.imgsrc;
                 newState[index] = imgItem;
                 //let newState = that.state.imgsrc.concat(imgItem);
                that.setState({
                    imgsrc:newState
                });
                //imagez.src = canvas.toDataURL('image/png')
              });

             });
           });
       }
reactjs html5-canvas
7个回答
7
投票

如果有人偶然发现此问题,错误消息将显示以下内容

Use different canvas or ensure previous operations were cancelled or completed.

获取文件时,如果已有文件,则必须将其销毁。即:

PDFJS.getDocument({ url: pdf_url }).promise
    .then((pdf_doc) => {

        if (this.pdf_doc) {
            this.pdf_doc.destroy();
        }
        this.pdf_doc = pdf_doc;
        this.total_pages = this.pdf_doc.numPages;
    })

我不知道这是否是一个好的解决方案,但至少它对我有用。


7
投票

在某些情况下,当 pdf 具有操作按钮(例如下一个/上一个或缩放)时,会显示此错误。 在这种情况下,通常您有一个渲染 pdf 页面的功能,例如:

renderPage(num) {
    // Using promise to fetch the page
    pdfDoc.getPage(num).then(function (page) {
        const viewport = page.getViewport({scale: scale});
        canvas.height = viewport.height;
        canvas.width = viewport.width;

        // Render PDF page into canvas context
        const renderContext = {
            canvasContext: ctx,
            viewport: viewport
        };
        page.render(renderContext);
    });
}

要修复错误,只需执行以下更改:

  1. 添加两个变量用于控制冲突和缓存等待页数:

    pageRendering = false; // Check conflict
    pageNumPending = null; // Cache waiting page number
    
  2. 按如下方式使用这些变量:

    renderPage(num) {
      if (this.pageRendering) { // Check if other page is rendering
        this.pageNumPending = num; // Cache waited page number until previous page rendering completed
      } else {
        this.pageRendering = true;
        // Using promise to fetch the page
        pdfDoc.getPage(num).then(function (page) {
            const viewport = page.getViewport({scale: scale});
            canvas.height = viewport.height;
            canvas.width = viewport.width;
    
            // Render PDF page into canvas context
            const renderContext = {
                canvasContext: ctx,
                viewport: viewport
            };
            const renderTask = page.render(renderContext);
    
            // Wait for rendering to finish
            renderTask.promise.then(function () {
                this.pageRendering = false;
                if (pageNumPending !== null) {
                    // Waited page must be rendered
                    this.renderPage(pageNumPending);
                    // Must be set to null to prevent infinite loop
                    this.pageNumPending = null;
                }
            });
        });
    

3
投票

我在使用 PDF.js 时遇到了完全相同的问题,解决方案是, 渲染完成后,您必须清除context

if (context) {
    context.clearRect(0, 0, canvas.width, canvas.height);
    context.beginPath();
}

这将确保上下文被清除并为下一次渲染做好准备,并且错误消失。

这对我有用。


3
投票

我遇到了和你一样的问题,但我的解决方案与之前发布的答案有点不同。

对我来说,问题在于我“不必要地通过状态更改重新渲染”。检查您是否在没有正确清除画布的情况下没有重新渲染组件,或者您是否甚至需要重新渲染(在我的例子中我不需要)。 希望这能有所帮助


3
投票

<div id="div_canvas"> <canvas id="cnv"></canvas> </div>

然后,在调用 pdf.js 函数之前,删除“div_canvas”内容并重新创建它:

$("#div_canvas").html(""); $("#div_canvas").html("<canvas id='cnv'></canvas>");



0
投票


0
投票

isPageRendering = false; pageQueue = []; self = this; renderPage(num, canvas) { if (self.isPageRendering) // Check if a given page is already rendering... self.pageQueue.push(num); // Enqueue page number until previous page rendering completed else { self.isPageRendering = true; // Using promise to fetch the page pdfDoc.getPage(num).then(function (page) { if (!canvas) canvas = $(`.pdf-canvas${num}`)[0]; //debugger; var viewport = page.getViewport({ scale: self.scale, rotation: self.rotation[num - 1] }); canvas.height = viewport.height; canvas.width = viewport.width; var ctx = canvas.getContext('2d'); // Render PDF page into canvas context var renderContext = { canvasContext: ctx, viewport: viewport }; const renderTask = page.render(renderContext); renderTask.promise.then(function () { //debugger; //console.log('Canvas data: ' + canvas.toDataURL()); // debugging self.isPageRendering = false; if (self.pageQueue.length > 0) self.renderPage(self.pageQueue.pop()); // recursive call to renderPage to render the remaining pages }); }); } }

	
© www.soinside.com 2019 - 2024. All rights reserved.