在浏览器中和安卓的webview中使用都没问题,但是Ios中的webview打开点开第三次时,只展示了第一页,第四次点开后就白屏不展示,并且报错:
null is not an object (evaluating 'groupCtx.scale')
问下原因,代码如下
<template>
<div class="pdf-container" ref="Pdfcontent">
<!--此处根据pdf的页数动态生成相应数量的canvas画布-->
<canvas
v-for="pageIndex in pdfPages"
:id="`pdf-canvas-${pageIndex}`"
:key="pageIndex"
></canvas>
</div>
</template>
<script setup>
import * as PdfJs from 'pdfjs-dist/legacy/build/pdf.js'
import { ref, onMounted, nextTick } from 'vue'
import 'pdfjs-dist/build/pdf.worker.entry'
PdfJs.GlobalWorkerOptions.workerSrc = import(
'pdfjs-dist/build/pdf.worker.entry'
)
let pdfDoc = ''
const pdfPages = ref(0)
let pdfScale = 1.0
const maxZoom = 40
const Pdfcontent = ref(null)
const props = defineProps({
pdfUrl: String,
isPdfReady: Boolean,
pdfStatus: String,
})
const emit = defineEmits(['update:isPdfReady', 'update:pdfStatus'])
function funloadFile(url) {
const loadingTask = PdfJs.getDocument(url)
loadingTask.promise.then((pdf) => {
pdfDoc = pdf
pdfPages.value = pdfDoc.numPages
pdf.getPage(1).then((res) => {
const boxWidth = Pdfcontent.value.clientWidth - 20
const [x1, , x2] = res._pageInfo.view
const pageWidth = x2 - x1
pdfScale = (boxWidth * (maxZoom / 10)) / pageWidth
})
nextTick(() => {
renderPage(1) // 表示渲染第 1 页
})
})
}
// num 表示渲染第几页
function renderPage(num) {
console.log('renderPage')
pdfDoc.getPage(num).then((page) => {
const canvasId = 'pdf-canvas-' + num // 第num个canvas画布的id
const canvas = document.getElementById(canvasId)
const ctx = canvas.getContext('2d')
const viewport = page.getViewport({ scale: pdfScale })
canvas.width = viewport.width
canvas.height = viewport.height
const clientWidth = Pdfcontent.value.clientWidth
canvas.style.width = clientWidth + 'px'
// 根据pdf每页的宽高比例设置canvas的高度
canvas.style.height =
clientWidth * (viewport.height / viewport.width) + 'px'
const renderContext = {
canvasContext: ctx,
viewport,
}
page.render(renderContext)
// 在第num页渲染完毕后,递归调用renderPage方法,去渲染下一页,直到所有页面渲染完毕为止
if (num < pdfPages.value) {
renderPage(num + 1)
} else {
emit('update:isPdfReady', true)
}
})
}
onMounted(() => {
funloadFile(props.pdfUrl)
})
</script>
<style scoped>
.pdf-container {
/* padding-right: 20px; */
width: 100%;
height: 100%;
overflow: scroll;
scrollbar-width: none; /* firefox */
-ms-overflow-style: none; /* IE 10+ */
}
.pdf-viewer::-webkit-scrollbar {
display: none; /* Chrome Safari */
}
</style>
这个问题可能是由于在iOS设备上,canvas的渲染性能问题导致的。你可以尝试以下方法来解决这个问题:
优化canvas的大小和缩放比例。确保canvas的大小适应设备的屏幕大小,同时避免使用过高的缩放比例,以减少渲染压力。
使用离屏canvas。将canvas绘制在一个新的canvas元素上,而不是直接在页面上绘制。这样可以避免因为页面重排和重绘导致的性能问题。示例代码如下:
<template>
<div class="pdf-container" ref="Pdfcontent">
<!--此处根据pdf的页数动态生成相应数量的canvas画布-->
<canvas
v-for="pageIndex in pdfPages"
:id="`pdf-canvas-${pageIndex}`"
:key="pageIndex"
></canvas>
</div>
</template>
<script>
import * as PdfJs from 'pdfjs-dist/legacy/build/pdf.js'
import { ref, onMounted, nextTick } from 'vue'
import 'pdfjs-dist/build/pdf.worker.entry'
PdfJs.GlobalWorkerOptions.workerSrc = import(
'pdfjs-dist/build/pdf.worker.entry'
)
let pdfDoc = ''
const pdfPages = ref(0)
let pdfScale = 1.0
const maxZoom = 40
const Pdfcontent = ref(null)
const props = defineProps({
pdfUrl: String,
isPdfReady: Boolean,
pdfStatus: String,
})
const emit = defineEmits(['update:isPdfReady', 'update:pdfStatus'])
function funloadFile(url) {
// ...省略其他代码
}
onMounted(() => {
funloadFile(props.pdfUrl)
})
</script>
<style scoped>
.pdf-container {
/* padding-right: 20px; */
width: 100%;
height: 100%;
overflow: scroll;
scrollbar-width: none; /* firefox */
-ms-overflow-style: none; /* IE 10+ */
}
.pdf-viewer::-webkit-scrollbar {
display: none; /* Chrome Safari */
}
</style>
【以下回答由 GPT 生成】
根据给出的代码和问题描述,我可以看到你正在使用pdf.js在iOS的webview上展示PDF文档。问题出现在第三次打开后只展示了第一页,第四次打开后变成白屏,并报错"null is not an object (evaluating 'groupCtx.scale')"。
这个问题可能是由于PDF文档没有正确地被释放导致的。为了解决这个问题,你可以尝试在每次加载新的PDF文档之前,先释放之前的文档。下面是具体的解决方案:
首先,你可以在Vue组件的beforeUnmount
钩子中添加一个方法来释放PDF文档,如下所示:
<script setup>
import { onBeforeUnmount } from 'vue'
onBeforeUnmount(() => {
if (pdfDoc) {
pdfDoc.destroy()
}
})
</script>
这样,在组件被销毁之前,会先执行这个方法来释放PDF文档。
接下来,你需要更新funloadFile
方法,在每次加载新的PDF文档之前,先调用pdfDoc.destroy()
释放之前的文档。修改后的代码如下:
function funloadFile(url) {
if (pdfDoc) {
pdfDoc.destroy()
}
const loadingTask = PdfJs.getDocument(url)
loadingTask.promise.then(function (pdf) {
pdfDoc = pdf
pdfPages.value = pdf.numPages
emit('update:isPdfReady', true)
emit('update:pdfStatus', '')
renderPages()
})
}
通过以上的修改,你可以在加载新的PDF文档之前先释放之前的文档,从而解决在iOS的webview上使用pdf.js出现白屏问题的情况。
注意:这个解决方案是基于我对问题的理解和经验的推测,因为我没有具体的环境和设备来测试这段代码,所以无法百分之百保证解决了问题。如果这个解决方案无效,请提供更多的信息和代码,以便我能更好地帮助你解决问题。
【相关推荐】