Error: Cannot use the same canvas during multiple render() operations. PDF.js issue
pdf.js
PDF Reader in JavaScript
项目地址:https://gitcode.com/gh_mirrors/pd/pdf.js
免费下载资源
·
现象:多次重复渲染后,偶发出现canvas绘制错误问题
解决思路:监听页面渲染进度,完成后加载下一页
核心源码:
完整源码组件如下:
<template>
<div class="pdf-view">
<canvas
class="canvas-screen-normal"
:id="`pdfCanvas${page}`"
v-for="page in dataMap.pdfPages"
:key="page"
></canvas>
</div>
</template>
<script setup lang="ts">
import { reactive, nextTick, watch, ref } from 'vue';
import * as PDF from 'pdfjs-dist';
import entry from 'pdfjs-dist/build/pdf.worker.entry'; // 引入时会报红线错误,不影响运行, 或在index.d.ts中声明declare
const props = defineProps({
height: {
type: String,
default: '',
},
width: {
type: String,
default: '',
},
// PDF文件路径url
pdfPath: {
type: String,
default: '',
},
});
watch(
() => props.pdfPath,
(newVal) => {
if (newVal) {
console.log('watch-pdfjsUrl:', newVal);
// 延迟加载,避免组件方法未初始化完成造成的加载错误问题
setTimeout(() => {
loadFile(newVal);
}, 100);
}
},
{ immediate: true, deep: true },
);
const dataMap = reactive<any>({
pdfPages: [], // 页数
pdfWidth: '', // 宽度
pdfDoc: '', // 文档内容
pdfScale: 2.0, // 放大倍数(如果预览内容模糊的情况可继续放大倍数增加清晰度)
pageRendering: false, // pdf页面是否正在渲染中
pageNumPending: null, // pdf正在加载中的页码
});
const loadFile = (url: string) => {
if (!PDF.GlobalWorkerOptions.workerSrc) {
PDF.GlobalWorkerOptions.workerSrc = entry;
}
console.log('loadPdfFile:', url);
let loadingTask = PDF.getDocument(url);
loadingTask.promise.then((pdf: any) => {
dataMap.pdfDoc = pdf;
dataMap.pdfPages = pdf.numPages;
nextTick(() => {
pdfStreamRenderPage(1);
});
});
};
const pdfStreamRenderPage = (num) => {
// 一串pdf64位的流
if (dataMap.pageRendering) {
dataMap.pageNumPending = num;
} else {
const pageNum = 1
renderPage(pageNum)
}
};
const renderPage = (num: number) => {
dataMap.pageRendering = true;
dataMap.pdfDoc.getPage(num).then((page: any) => {
let canvas: any = document.getElementById('pdfCanvas' + num);
let ctx = canvas.getContext('2d');
let dpr = window.devicePixelRatio || 1;
let bsr =
ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio ||
1;
let ratio = dpr / bsr;
let viewport = page.getViewport({ scale: dataMap.pdfScale });
canvas.width = viewport.width * ratio;
canvas.height = viewport.height * ratio;
// canvas.style.width = viewport.width + "px";
// canvas.style.height = viewport.height + "px";
canvas.style.width = '100%';
canvas.style.height = '100%';
// dataMap.pdfWidth = viewport.width + 'px';
// 将 PDF 页面渲染到 canvas 上下文中
let renderContext = {
transform: [ratio, 0, 0, ratio, 0, 0], //同比例缩放
canvasContext: ctx,
viewport: viewport,
};
// 解决如果操作频率过快或者多次执行页面展示的pdf文件内容丢失,展示不完整,内容倒置等现象。
// 打开控制台发现有报错信息:ERROR Error: Uncaught (in promise): Error: Cannot use the same canvas during multiple render() operations. Use different canvas or ensure previous operations were cancelled or completed
const renderTask = page.render(renderContext);
// Wait for rendering to finish
renderTask.promise.then(() => {
dataMap.pageRendering = false;
num++;
if (num <= dataMap.pdfPages) {
// scale next canvas
renderPage(num)
}
if (dataMap.pageNumPending !== null) {
// New page rendering is pending
pdfStreamRenderPage(dataMap.pageNumPending);
dataMap.pageNumPending = null;
}
});
});
};
</script>
<style lang="less" scoped>
.pdf-view {
width: 100%;
margin: 0 auto;
border: 1px solid #e4ebf1;
position: relative;
overflow: scroll;
overflow-x: hidden;
.canvas-screen-normal {
width: 100% !important;
height: auto !important;
display: block;
border-bottom: 1px solid #e4ebf1;
}
canvas:last-child {
border-bottom: none;
}
}
</style>
GitHub 加速计划 / pd / pdf.js
47.48 K
9.86 K
下载
PDF Reader in JavaScript
最近提交(Master分支:3 个月前 )
18284815
[Editor] Update the disclaimer string in the new alt-text dialog (bug 1911738) 3 个月前
fc602c65
And tweak the css in order to take into account that disclaimer can be on two (or more lines).
3 个月前
更多推荐
已为社区贡献1条内容
所有评论(0)