feat: 优化了PDF插件的相关表现
This commit is contained in:
1 parent
c595ebb260
commit
f6c1ba199f
3 files changed
+119
-17
No files matched your search
@@ -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
@@ -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')
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+109
-14
@@ -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);
|
||||||
.miao-container-pdf {
|
overflow-y: hidden;
|
||||||
max-width: 100%;
|
|
||||||
max-height: 100%;
|
|
||||||
overflow: scroll;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
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 {
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
.page {
|
.page {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
transform: scale(0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas {
|
canvas {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
border-bottom: 1px solid black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.miao-container-loading {
|
||||||
|
position: absolute;
|
||||||
|
top: 40px;
|
||||||
|
background-color: aliceblue;
|
||||||
|
border: 1px solid black;
|
||||||
|
height: 40px;
|
||||||
|
width: 400px;
|
||||||
|
border-radius: 10px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 20px;
|
||||||
|
letter-spacing: 5px;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
Reference in new issue
Block a user