如何解决此错误在多次render()操作期间无法使用同一画布

时间:2018-09-05 13:25:27

标签: reactjs html5-canvas

我正在使用canvas进行反应,并使用画布将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')
              });

             });
           });
       }

4 个答案:

答案 0 :(得分:1)

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

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

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

这对我有用。

答案 1 :(得分:0)

万一有人偶然发现此错误,错误消息将指出以下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;
    })

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

答案 2 :(得分:0)

我遇到了与您完全相同的问题,但是我的解决方案与先前发布的答案有所不同。

对我来说,问题在于我由于状态更改而不必要地重新渲染。检查您是否在没有正确清除画布的情况下不重新渲染组件,或者甚至根本不需要重新渲染(对于我而言,我没有这样做)。

希望这会有所帮助

答案 3 :(得分:0)

这很好用。在加载其他文档之前,我使用变量来存储实例并销毁它:

var PDFInstance: any = undefined
var currentSignature_axisX = 1
var currentSignature_axisY = 1

useEffect(() => { if (pdfUrl != undefined) renderPDF() }, [pdfUrl])
const renderPDF = async () => {

setLoadingPDF(true)
const urlSlice = pdfUrl.split('/')
const key = `${urlSlice[3]}/${urlSlice[4]}/${urlSlice[5]}`

Storage.configure({ customPrefix: { public: '' }, })
const pdfS3URL = await Storage.get(key)

pdfjsLib.GlobalWorkerOptions.workerSrc = workerSrc
if (PDFInstance) PDFInstance.destroy()

PDFInstance = await pdfjsLib.getDocument(pdfS3URL).promise
const page = await PDFInstance.getPage(1)
const viewport = page.getViewport({ scale: 1 })
const context = pdfCanvasRef.current?.getContext('2d');

setCanvasHeight(viewport.height)
setCanvasWidth(viewport.width)

const renderContext = {
  canvasContext: context,
  viewport: viewport,
}
await page.render(renderContext).promise
setLoadingPDF(false)

}