如何修复此错误在多个渲染()操作期间无法使用相同的画布
Posted
技术标签:
【中文标题】如何修复此错误在多个渲染()操作期间无法使用相同的画布【英文标题】:how to fix this Error Cannot use the same canvas during multiple render() operations 【发布时间】:2019-02-10 16:01:32 【问题描述】:我在反应中使用画布,并使用画布将 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')
);
);
);
【问题讨论】:
【参考方案1】:如果有人偶然发现此问题,错误消息会显示以下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】:我在使用 PDF.js 时遇到了完全相同的问题,解决方案是, 渲染完成后,您必须清除 上下文。
if (context)
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
这将确保上下文被清除并为下一次渲染做好准备,并且错误消失。
这对我有用。
【讨论】:
遗憾的是,这并没有为我解决。在我的情况下,它试图在第一次尚未完成渲染时再次加载另一个相同的 pdf。我想我需要等待第一个过程完成或取消它。你会怎么做这两件事? 晚会很晚。PDFJS.getDocument()
返回的对象,具有promise
字段,也具有cancel
函数。调用它,它将取消当前渲染并拒绝promise
对象。然后,您可以再次安全地拨打PDFJS.getDocument()
。【参考方案3】:
为了避免这种情况,请将你的canvas对象放在一个div对象中,如下所示:
<div id="div_canvas">
<canvas id="cnv"></canvas>
</div>
然后,在调用 pdf.js 函数之前,删除“div_canvas”内容并重新创建它:
$("#div_canvas").html("");
$("#div_canvas").html("<canvas id='cnv'></canvas>");
【讨论】:
【参考方案4】:我和你有同样的问题,但我的解决方案与之前发布的答案有点不同。
对我而言,问题在于我在状态更改时不必要地重新渲染。检查您是否在未正确清除画布的情况下重新渲染组件,或者您是否甚至需要重新渲染(在我的情况下我没有)。
希望这能有所帮助
【讨论】:
【参考方案5】:这很好用。我使用一个变量来存储实例并在加载其他文档之前将其销毁:
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)
【讨论】:
【参考方案6】:为了避免这种情况,请将您的画布对象放在一个 div 对象中,如下所示。 然后,在调用 pdf.js 函数之前,删除“div_canvas”内容并重新创建它:
"HTML"
<div id="div_canvas">
<canvas id="cnv"></canvas>
</div>
.....
"JS FILE"
$("#div_canvas").html("");
$("#div_canvas").html("<canvas id='cnv'></canvas>");
它对我来说很好,我希望它对某人有帮助!
【讨论】:
以上是关于如何修复此错误在多个渲染()操作期间无法使用相同的画布的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Remote-SSH 修复 VS Code 错误:“终端进程无法启动:启动期间发生本机异常(forkpty(3)失败。)。”?
如何修复使用 combine 解析 json 期间描述的错误?
如何在sails.js 中的SocketIO 握手期间修复“此套接字没有可用的有效会话”?
如何修复此错误 3734:无法在 MySQL WorkBench 上添加外键约束?