feat: 优化了PDF插件的相关表现

This commit is contained in:
539943419 committed 2024-08-28 20:27:48 +08:00
1 parent c595ebb260
commit f6c1ba199f
3 files changed
+122 -20

No files matched your search

+1
View File
@@ -332,6 +332,7 @@ $tag-width: 170px;
.view-container-item { .view-container-item {
flex: 1; flex: 1;
height: 100%; height: 100%;
min-width: 0;
} }
&::-webkit-scrollbar { &::-webkit-scrollbar {
+9 -3
View File
@@ -42,16 +42,22 @@ export default function init() {
'miaoIframe', 'miaoIframe',
'框架', '框架',
MiaoIframe, MiaoIframe,
(vDirs, vFiles) => { () => {
return false return false
} }
) )
pluginCenter.registerComponent( pluginCenter.registerComponent(
'miaoPDF', 'miaoPDF',
'PDF', 'PDF浏览',
MiaoPDF, MiaoPDF,
(vDirs, vFiles) => { (vDirs, vFiles) => {
return true if (vDirs.length !== 0) {
return false
}
if (vFiles.length !== 1) {
return false
}
return vFiles[0].name.endsWith('pdf')
} }
) )
} }
+112 -17
View File
@@ -1,13 +1,24 @@
<template> <template>
<div class="miao-container"> <div class="miao-container">
<div ref="pdfEl" class="miao-container-pdf"></div> <div class="miao-container-topBar">
<div class="miao-container-topBar-btn" @click="() => handleZoom(10)" title="快速缩小">--</div>
<div class="miao-container-topBar-btn" @click="() => handleZoom()" title="缩小">-</div>
<div class="miao-container-topBar-btn" @click="() => handleResetMargin()" title="还原">还原缩放</div>
<div class="miao-container-topBar-btn" @click="() => handleShrink()" title="放大">+</div>
<div class="miao-container-topBar-btn" @click="() => handleShrink(10)" title="快速放大">++</div>
</div>
<NScrollbar>
<div ref="pdfEl" class="miao-container-pdf" :style="{ margin: `0 ${pdfMargin}px` }"></div>
</NScrollbar>
<div class="miao-container-loading" v-if="isLoading">加载中,加载进度:{{ loadingPercent === -1 ? '缓存中' : `${canvasList.length}/${pdfPageCount}` }}</div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref } from 'vue' import { computed, onMounted, ref, shallowReactive } from 'vue'
import PdfjsWorker from 'pdfjs-dist/build/pdf.worker.mjs?worker' import PdfjsWorker from 'pdfjs-dist/build/pdf.worker.mjs?worker'
import { VirtualFile } from '@/class/VirtualDirectory' import { VirtualFile } from '@/class/VirtualDirectory'
import { NScrollbar } from 'naive-ui';
const currentFiles = defineModel<VirtualFile[]>('currentFiles', { const currentFiles = defineModel<VirtualFile[]>('currentFiles', {
required: true required: true
@@ -15,6 +26,41 @@ const currentFiles = defineModel<VirtualFile[]>('currentFiles', {
const pdfEl = ref<HTMLDivElement>() const pdfEl = ref<HTMLDivElement>()
// 通过margin来实现缩小功能
const pdfMargin = ref<number>(0)
const pdfPageCount = ref<number>(-1)
const isLoading = computed(() => {
return canvasList.length !== pdfPageCount.value
})
const canvasList = shallowReactive<HTMLCanvasElement[]>([])
const handleZoom = (index?: number) => {
const _index = index ?? 1
pdfMargin.value += 10 * _index
}
const handleShrink = (index?: number) => {
const _index = index ?? 1
if (pdfMargin.value - 10 * _index <= 0) {
return pdfMargin.value = 0
}
pdfMargin.value -= 10 * _index
}
const handleResetMargin = () => {
pdfMargin.value = 0
}
const loadingPercent = computed(() => {
if(pdfPageCount.value === -1) {
return -1
}
return canvasList.length / pdfPageCount.value
})
onMounted(async () => { onMounted(async () => {
const pdfSrc = currentFiles.value[0].url const pdfSrc = currentFiles.value[0].url
// @ts-ignore // @ts-ignore
@@ -26,19 +72,17 @@ onMounted(async () => {
let loadingTask = PDFJS.getDocument({ url: pdfSrc }) let loadingTask = PDFJS.getDocument({ url: pdfSrc })
loadingTask.__PDFDocumentLoadingTask = true loadingTask.__PDFDocumentLoadingTask = true
const pdf = await loadingTask.promise // 使用await等待加载完毕 const pdf = await loadingTask.promise // 使用await等待加载完毕
pdfPageCount.value = pdf.numPages
// 循环渲染每一页 // 循环渲染每一页
for (let i = 1; i <= pdf.numPages; i++) { for (let i = 1; i <= pdf.numPages; i++) {
const page = await pdf.getPage(i) const page = await pdf.getPage(i)
let pixelRatio = 3 let pixelRatio = 3
let viewport = page.getViewport({ scale: 1 }) let viewport = page.getViewport({ scale: 1 })
let divPage = window.document.createElement('div') // canvas的外层div
// 使用canvas渲染 // 使用canvas渲染
let canvas = divPage.appendChild( let canvas = window.document.createElement('canvas')
window.document.createElement('canvas') canvasList.push(canvas)
)
divPage.className = 'page'
// @ts-ignore // @ts-ignore
pdfEl.value.appendChild(divPage) pdfEl.value.appendChild(canvas)
canvas.width = viewport.width * pixelRatio // 计算宽度 canvas.width = viewport.width * pixelRatio // 计算宽度
canvas.height = viewport.height * pixelRatio canvas.height = viewport.height * pixelRatio
let renderContext = { let renderContext = {
@@ -47,9 +91,7 @@ onMounted(async () => {
transform: [pixelRatio, 0, 0, pixelRatio, 0, 0] transform: [pixelRatio, 0, 0, pixelRatio, 0, 0]
} }
await page.render(renderContext).promise // 一页一页的渲染 await page.render(renderContext).promise // 一页一页的渲染
divPage.className = 'page complete'
} }
console.log('pdf页面全部渲染完毕', pdf.numPages, pdf)
}) })
</script> </script>
@@ -58,22 +100,75 @@ onMounted(async () => {
width: 100%; width: 100%;
height: 100%; height: 100%;
background-color: rgb(53, 53, 53); background-color: rgb(53, 53, 53);
overflow-y: hidden;
display: flex;
flex-direction: column;
align-items: center;
.miao-container-topBar {
box-sizing: border-box;
padding: 0 30px;
height: 30px;
width: 100%;
background-color: rgb(170, 176, 182);
display: flex;
justify-content: space-around;
align-items: center;
&-btn {
cursor: pointer;
user-select: none;
height: 80%;
padding: 0 5px;
display: flex;
align-items: center;
justify-content: center;
font-size: larger;
letter-spacing: 1px;
color: black;
border-radius: 5px;
&:hover {
background-color: #eaeaea42;
}
}
}
.miao-container-pdf { .miao-container-pdf {
min-width: 0;
max-width: 100%; max-width: 100%;
max-height: 100%; max-height: 100%;
overflow: scroll;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center;
.page {
display: flex;
justify-content: center;
align-items: center;
transform: scale(0.5);
}
canvas {
width: 100%;
height: 100%;
border-bottom: 1px solid black;
}
} }
.page {
.miao-container-loading {
position: absolute;
top: 40px;
background-color: aliceblue;
border: 1px solid black;
height: 40px;
width: 400px;
border-radius: 10px;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} font-size: 20px;
canvas { letter-spacing: 5px;
width: 100%; user-select: none;
height: 100%;
} }
} }
</style> </style>