Error: Cannot use the same canvas during multiple render() operations. PDF.js issue
Error: Cannot use the same canvas during multiple render() operations. PDF.js issue
我正在使用 angularjs(客户端)项目开发 Web 应用程序 (c#)。
我们要求在带有 next/previous 按钮选项的网页上显示 pdf。
为此,我们使用了 pdf.js(由 Mozilla 基金会提供),并且我们已经按照给定的示例实现了代码。
我们已经创建了一个 angular 指令来确保一切正常。
第一次加载页面时一切正常,现在进入重点:
加载新源后 URL 抛出以下错误:
pdf.js?v=1641729671:12170 Uncaught (in promise) Error: Cannot use the same canvas during multiple render() operations. Use different canvas or ensure previous operations were cancelled or completed.
at InternalRenderTask.initializeGraphics (pdf.js?v=1641729671:12170)
at pdf.js?v=1641729671:10666
我已经尝试了以下方法:
- 尝试通过重新链接指令呈现 pdf。
- 试图通过页面清理功能呈现所有 pdf,但仍然会导致问题。
- 尝试通过取消中间的页面来呈现 pdf 页面,但它不起作用。
- 试图清除 canvas 和上下文并重新初始化它,但没有成功。
- 尝试通过不同的不同 IDS 创建动态 canvases,但没有成功。
- 尝试分配 class 而不是 pdf 查看器的 Id,但没有成功。
我研究了 google 但我没有得到任何有效的解决方案 :(
现在让我 post 我的客户端代码以便更好地理解。
下面是我的指令代码:
angular.module('angularPDFView', [])
.directive('pdfviewer', ['$parse', function ($parse) {
var canvas = null;
var instance_id = null;
var context = null;
return {
restrict: "E",
template: '<canvas></canvas>',
scope: {
onPageLoad: '&',
loadProgress: '&',
src: '@',
id: '='
},
controller: ['$scope', function ($scope) {
$scope.pageNum = 1;
$scope.pdfDoc = null;
$scope.scale = 1.0;
$scope.rotation = 0;
$scope.pageNumPending = null;
$scope.renderTask;
$scope.path = null;
$scope.getRandomSpan = function () {
return Math.floor(Math.random() * 1000000000);
};
$scope.loadPDF = function (path) {
$scope.path = path;
var randNum = $scope.getRandomSpan();
pdfjsLib.GlobalWorkerOptions.workerSrc = '/Content/js/pdf.worker.js?v=' + randNum;
console.log('loadPDF ', path);
$scope.scale = 1.0;
$scope.rotation = 0;
var loadingTask = pdfjsLib.getDocument(path);
loadingTask.promise.then(function (_pdfDoc) {
$scope.pdfDoc = _pdfDoc;
$scope.renderPage($scope.pageNum);
});
};
$scope.renderPage = function (num) {
pageRendering = true;
// Using promise to fetch the page
$scope.pdfDoc.getPage(num).then(function (page) {
if ($scope.renderTask) {
try {
$scope.renderTask.cancel();
} catch (e) {
//
}
}
var viewport = page.getViewport({ scale: $scope.scale });
canvas.height = viewport.height;
canvas.width = viewport.width;
// Render PDF page into canvas context
var renderContext = {
canvasContext: context,
viewport: viewport,
continueCallback: function (cont) {
cont();
}
};
$scope.renderTask = page.render(renderContext);
// Wait for rendering to finish
try {
$scope.renderTask.promise.then(function () {
pageRendering = false;
if ($scope.pageNumPending !== null) {
// New page rendering is pending
$scope.renderPage($scope.pageNumPending);
$scope.pageNumPending = null;
}
$scope.$apply(function () {
$scope.onPageLoad({
page: $scope.pageNum,
total: $scope.pdfDoc.numPages
});
});
});
} catch (e) {
//
}
});
// Update page counters
$scope.pageNum = num;
};
$scope.queueRenderPage = function (num) {
if (context) {
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
}
if ($scope.pageRendering) {
$scope.pageNumPending = num;
} else {
$scope.renderPage(num);
}
};
$scope.$on('pdfviewer.prevPage', function () {
if ($scope.pageNum <= 1) {
return;
}
$scope.pageNum--;
$scope.queueRenderPage($scope.pageNum);
});
/**
* Displays next page.
*/
$scope.$on('pdfviewer.nextPage', function () {
if ($scope.pageNum >= $scope.pdfDoc.numPages) {
return;
}
$scope.pageNum++;
$scope.queueRenderPage($scope.pageNum);
});
$scope.$on('pdfviewer.gotoPage', function (evt, id, page) {
if (id !== instance_id) {
return;
}
if ($scope.pdfDoc === null) {
$scope.pageNum = page;
$scope.loadPDF($scope.path);
} else {
if (page >= 1 && page <= $scope.pdfDoc.numPages) {
$scope.pageNum = page;
$scope.renderPage($scope.pageNum);
}
}
});
}],
link: function (scope, iElement, iAttr) {
canvas = iElement.find('canvas')[0];
context = canvas.getContext('2d');
instance_id = iAttr.id;
iAttr.$observe('src', function (v) {
console.log('src attribute changed, new value is', v);
if (v !== undefined && v !== null && v !== '') {
scope.pageNum = 1;
scope.loadPDF(scope.src);
}
});
}
};
}])
.service("angularPDFViewerService", ['$rootScope', function ($rootScope) {
var svc = {};
svc.nextPage = function () {
$rootScope.$broadcast('pdfviewer.nextPage');
};
svc.prevPage = function () {
$rootScope.$broadcast('pdfviewer.prevPage');
};
svc.Instance = function (id) {
var instance_id = id;
return {
prevPage: function () {
$rootScope.$broadcast('pdfviewer.prevPage');
},
nextPage: function () {
$rootScope.$broadcast('pdfviewer.nextPage');
},
gotoPage: function (page) {
$rootScope.$broadcast('pdfviewer.gotoPage', instance_id, page);
}
};
};
return svc;
}]);
..
如何取消渲染操作或有什么方法可以使用不同的 canvas 加载 PDF 吗?
如有任何帮助,我们将不胜感激。
提前致谢!
使用 "render in progress" 标志:
var renderInProgress;
var renderTask;
if (renderInProgress) {
//ensure previous operations were cancelled or completed.
.then(function() {
renderTask = doRender();
});
} else {
renderTask = doRender();
};
function doRender() {
renderInProgress = true;
var renderOp = page.render(renderContext);
renderOp.promise = renderOp.promise.then(function () {
//Do whatever
}).finally(function() {
renderInProgress = false;
});
return renderOp;
}
经过两天的努力,我终于解决了 pdf 加载问题,控制台错误仍然存在,但现在功能正常:)
我发布的答案可能对某人有帮助,以下是我执行的一些小步骤:
访问:https://cdnjs.com/libraries/pdf.js
我已经从上述 link 下载了最新版本的 PDF.js 和 Pdf-worker.js。
只是用更新的参考库替换了我的旧参考库,仅此而已。
它现在在我的 angular 应用程序中非常有效!!!
我正在使用 angularjs(客户端)项目开发 Web 应用程序 (c#)。 我们要求在带有 next/previous 按钮选项的网页上显示 pdf。 为此,我们使用了 pdf.js(由 Mozilla 基金会提供),并且我们已经按照给定的示例实现了代码。 我们已经创建了一个 angular 指令来确保一切正常。 第一次加载页面时一切正常,现在进入重点:
加载新源后 URL 抛出以下错误:
pdf.js?v=1641729671:12170 Uncaught (in promise) Error: Cannot use the same canvas during multiple render() operations. Use different canvas or ensure previous operations were cancelled or completed.
at InternalRenderTask.initializeGraphics (pdf.js?v=1641729671:12170) at pdf.js?v=1641729671:10666
我已经尝试了以下方法:
- 尝试通过重新链接指令呈现 pdf。
- 试图通过页面清理功能呈现所有 pdf,但仍然会导致问题。
- 尝试通过取消中间的页面来呈现 pdf 页面,但它不起作用。
- 试图清除 canvas 和上下文并重新初始化它,但没有成功。
- 尝试通过不同的不同 IDS 创建动态 canvases,但没有成功。
- 尝试分配 class 而不是 pdf 查看器的 Id,但没有成功。
我研究了 google 但我没有得到任何有效的解决方案 :( 现在让我 post 我的客户端代码以便更好地理解。
下面是我的指令代码:
angular.module('angularPDFView', [])
.directive('pdfviewer', ['$parse', function ($parse) {
var canvas = null;
var instance_id = null;
var context = null;
return {
restrict: "E",
template: '<canvas></canvas>',
scope: {
onPageLoad: '&',
loadProgress: '&',
src: '@',
id: '='
},
controller: ['$scope', function ($scope) {
$scope.pageNum = 1;
$scope.pdfDoc = null;
$scope.scale = 1.0;
$scope.rotation = 0;
$scope.pageNumPending = null;
$scope.renderTask;
$scope.path = null;
$scope.getRandomSpan = function () {
return Math.floor(Math.random() * 1000000000);
};
$scope.loadPDF = function (path) {
$scope.path = path;
var randNum = $scope.getRandomSpan();
pdfjsLib.GlobalWorkerOptions.workerSrc = '/Content/js/pdf.worker.js?v=' + randNum;
console.log('loadPDF ', path);
$scope.scale = 1.0;
$scope.rotation = 0;
var loadingTask = pdfjsLib.getDocument(path);
loadingTask.promise.then(function (_pdfDoc) {
$scope.pdfDoc = _pdfDoc;
$scope.renderPage($scope.pageNum);
});
};
$scope.renderPage = function (num) {
pageRendering = true;
// Using promise to fetch the page
$scope.pdfDoc.getPage(num).then(function (page) {
if ($scope.renderTask) {
try {
$scope.renderTask.cancel();
} catch (e) {
//
}
}
var viewport = page.getViewport({ scale: $scope.scale });
canvas.height = viewport.height;
canvas.width = viewport.width;
// Render PDF page into canvas context
var renderContext = {
canvasContext: context,
viewport: viewport,
continueCallback: function (cont) {
cont();
}
};
$scope.renderTask = page.render(renderContext);
// Wait for rendering to finish
try {
$scope.renderTask.promise.then(function () {
pageRendering = false;
if ($scope.pageNumPending !== null) {
// New page rendering is pending
$scope.renderPage($scope.pageNumPending);
$scope.pageNumPending = null;
}
$scope.$apply(function () {
$scope.onPageLoad({
page: $scope.pageNum,
total: $scope.pdfDoc.numPages
});
});
});
} catch (e) {
//
}
});
// Update page counters
$scope.pageNum = num;
};
$scope.queueRenderPage = function (num) {
if (context) {
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
}
if ($scope.pageRendering) {
$scope.pageNumPending = num;
} else {
$scope.renderPage(num);
}
};
$scope.$on('pdfviewer.prevPage', function () {
if ($scope.pageNum <= 1) {
return;
}
$scope.pageNum--;
$scope.queueRenderPage($scope.pageNum);
});
/**
* Displays next page.
*/
$scope.$on('pdfviewer.nextPage', function () {
if ($scope.pageNum >= $scope.pdfDoc.numPages) {
return;
}
$scope.pageNum++;
$scope.queueRenderPage($scope.pageNum);
});
$scope.$on('pdfviewer.gotoPage', function (evt, id, page) {
if (id !== instance_id) {
return;
}
if ($scope.pdfDoc === null) {
$scope.pageNum = page;
$scope.loadPDF($scope.path);
} else {
if (page >= 1 && page <= $scope.pdfDoc.numPages) {
$scope.pageNum = page;
$scope.renderPage($scope.pageNum);
}
}
});
}],
link: function (scope, iElement, iAttr) {
canvas = iElement.find('canvas')[0];
context = canvas.getContext('2d');
instance_id = iAttr.id;
iAttr.$observe('src', function (v) {
console.log('src attribute changed, new value is', v);
if (v !== undefined && v !== null && v !== '') {
scope.pageNum = 1;
scope.loadPDF(scope.src);
}
});
}
};
}])
.service("angularPDFViewerService", ['$rootScope', function ($rootScope) {
var svc = {};
svc.nextPage = function () {
$rootScope.$broadcast('pdfviewer.nextPage');
};
svc.prevPage = function () {
$rootScope.$broadcast('pdfviewer.prevPage');
};
svc.Instance = function (id) {
var instance_id = id;
return {
prevPage: function () {
$rootScope.$broadcast('pdfviewer.prevPage');
},
nextPage: function () {
$rootScope.$broadcast('pdfviewer.nextPage');
},
gotoPage: function (page) {
$rootScope.$broadcast('pdfviewer.gotoPage', instance_id, page);
}
};
};
return svc;
}]);
..
如何取消渲染操作或有什么方法可以使用不同的 canvas 加载 PDF 吗?
如有任何帮助,我们将不胜感激。 提前致谢!
使用 "render in progress" 标志:
var renderInProgress;
var renderTask;
if (renderInProgress) {
//ensure previous operations were cancelled or completed.
.then(function() {
renderTask = doRender();
});
} else {
renderTask = doRender();
};
function doRender() {
renderInProgress = true;
var renderOp = page.render(renderContext);
renderOp.promise = renderOp.promise.then(function () {
//Do whatever
}).finally(function() {
renderInProgress = false;
});
return renderOp;
}
经过两天的努力,我终于解决了 pdf 加载问题,控制台错误仍然存在,但现在功能正常:)
我发布的答案可能对某人有帮助,以下是我执行的一些小步骤:
访问:https://cdnjs.com/libraries/pdf.js
我已经从上述 link 下载了最新版本的 PDF.js 和 Pdf-worker.js。 只是用更新的参考库替换了我的旧参考库,仅此而已。
它现在在我的 angular 应用程序中非常有效!!!