Vue.js中PDF.js偶现页面倒置及渲染报错问题排查
Vue.js 集成 PDF.js 时页面倒置+重复渲染报错的解决方案
问题现象
- PDF页面偶尔出现显示倒置的情况
- 控制台抛出错误:
pdf.min.js:22 Uncaught (in promise) Error: Cannot use the same canvas during multiple render() operations. Use different canvas or ensure previous operations were cancelled or completed. - 即便用Promise处理了页面渲染逻辑,问题仍然存在
问题复现代码
<template> <canvas ref="pdfCanvas"></canvas> </template> <script> import * as pdfjsLib from 'pdfjs-dist' import 'pdfjs-dist/build/pdf.worker.entry' export default { data() { return { pdfDoc: null, currentPage: 1 } }, methods: { async loadPdf(url) { this.pdfDoc = await pdfjsLib.getDocument(url).promise this.renderPage(this.currentPage) }, async renderPage(pageNum) { const page = await this.pdfDoc.getPage(pageNum) const canvas = this.$refs.pdfCanvas const ctx = canvas.getContext('2d') const viewport = page.getViewport({ scale: 1.5 }) canvas.width = viewport.width canvas.height = viewport.height // 直接发起渲染,未处理上一次的渲染任务 await page.render({ canvasContext: ctx, viewport }).promise } } } </script>
修复后无异常代码
<template> <canvas ref="pdfCanvas"></canvas> </template> <script> import * as pdfjsLib from 'pdfjs-dist' import 'pdfjs-dist/build/pdf.worker.entry' export default { data() { return { pdfDoc: null, currentPage: 1, renderTask: null // 保存当前渲染任务 } }, methods: { async loadPdf(url) { this.pdfDoc = await pdfjsLib.getDocument(url).promise this.renderPage(this.currentPage) }, async renderPage(pageNum) { // 先取消上一次未完成的渲染任务 if (this.renderTask) { this.renderTask.cancel() } const page = await this.pdfDoc.getPage(pageNum) const canvas = this.$refs.pdfCanvas const ctx = canvas.getContext('2d') // 读取页面旋转角度,修正视口 const rotate = page.rotate const viewport = page.getViewport({ scale: 1.5, rotate }) canvas.width = viewport.width canvas.height = viewport.height // 清空画布避免残留内容 ctx.clearRect(0, 0, canvas.width, canvas.height) // 保存当前渲染任务,便于后续取消 this.renderTask = page.render({ canvasContext: ctx, viewport }) try { await this.renderTask.promise } catch (err) { // 仅捕获非取消类的渲染异常 if (!err.message.includes('cancelled')) { console.error('PDF渲染失败:', err) } } finally { this.renderTask = null } } }, beforeUnmount() { // 组件销毁前清理未完成的渲染任务 if (this.renderTask) { this.renderTask.cancel() } } } </script>
修复关键点说明
- 避免并发渲染冲突:新增
renderTask变量追踪当前渲染任务,每次渲染前取消上一次未完成的任务,彻底解决同一个canvas被多渲染操作占用的问题。 - 修正页面旋转:读取PDF页面原生的
rotate属性,创建视口时传入该参数,解决页面倒置的问题。 - 画布清理与异常处理:渲染前清空画布避免残留内容,捕获渲染取消的异常,防止控制台出现无效报错。
- 组件销毁时清理:在
beforeUnmount钩子中取消未完成的渲染任务,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Qiuzman
相关产品推荐
相关产品推荐

