feat(OfficePdf):Lazy loading

VueOfficePdf has added lazy loading functionality, where it initially loads 5 pages by default and subsequently implements lazy loading as you scroll.
This commit is contained in:
lianxin 2023-08-15 15:09:54 +08:00
parent f03c6b1de9
commit 92e6a70f52

View File

@ -1,9 +1,9 @@
<script> <script>
import {defineComponent, ref, onMounted, watch} from 'vue-demi'; import { defineComponent, ref, onMounted, watch } from 'vue-demi';
import workerStr from './worker?raw'; import workerStr from './worker?raw';
import pdfjsLib from './pdf?raw'; import pdfjsLib from './pdf?raw';
import {download as downloadFile, getUrl, loadScript} from '../../../utils/url'; import { download as downloadFile, getUrl, loadScript } from '../../../utils/url';
import {base64_encode} from '../../../utils/base64'; import { base64_encode } from '../../../utils/base64';
import omit from 'lodash/omit'; import omit from 'lodash/omit';
const pdfJsLibSrc = `data:text/javascript;base64,${(base64_encode(pdfjsLib))}`; const pdfJsLibSrc = `data:text/javascript;base64,${(base64_encode(pdfjsLib))}`;
@ -27,17 +27,20 @@ export default defineComponent({
} }
}, },
emits: ['rendered', 'error'], emits: ['rendered', 'error'],
setup(props, {emit}) { setup(props, { emit }) {
let pdfDocument = null; let pdfDocument = null;
let loadingTask = null; let loadingTask = null;
const rootRef = ref([]); const rootRef = ref([]);
const numPages = ref(0); const numPages = ref(0);
const lazySize = ref(5);
const pageSize = ref(lazySize.value);
function installPdfScript() { function installPdfScript() {
return loadScript(pdfJsLibSrc).then(() => { return loadScript(pdfJsLibSrc).then(() => {
if(window.pdfjsLib){ if (window.pdfjsLib) {
window.pdfjsLib.GlobalWorkerOptions.workerSrc = PdfJsWorkerSrc; window.pdfjsLib.GlobalWorkerOptions.workerSrc = PdfJsWorkerSrc;
}else{ } else {
return Promise.reject('window.pdfjsLib未找到'); return Promise.reject('window.pdfjsLib未找到');
} }
}); });
@ -64,16 +67,26 @@ export default defineComponent({
}); });
loadingTask.promise.then((pdf) => { loadingTask.promise.then((pdf) => {
pdfDocument = pdf; pdfDocument = pdf;
numPages.value = pdfDocument.numPages; numPages.value = Math.min(pdfDocument.numPages, lazySize.value);
renderPage(1); renderPage(1);
}).catch((e) => { }).catch((e) => {
emit('error', e); emit('error', e);
}); });
} }
function onScrollPdf(e) {
const { scrollTop, scrollHeight, clientHeight } = e.target;
if (scrollTop + clientHeight >= scrollHeight) {
if (numPages.value < pdfDocument.numPages) {
numPages.value += Math.min(lazySize.value, pdfDocument.numPages)
renderPage(1);
}
}
}
function renderPage(num) { function renderPage(num) {
pdfDocument.getPage(num).then((pdfPage) => { pdfDocument.getPage(num).then((pdfPage) => {
const viewport = pdfPage.getViewport({scale: 2}); const viewport = pdfPage.getViewport({ scale: 2 });
const outputScale = window.devicePixelRatio || 1; const outputScale = window.devicePixelRatio || 1;
const canvas = rootRef.value[num - 1]; const canvas = rootRef.value[num - 1];
@ -89,7 +102,7 @@ export default defineComponent({
domWidth = Math.floor(props.options.width); domWidth = Math.floor(props.options.width);
domHeight = Math.floor(domHeight * scale); domHeight = Math.floor(domHeight * scale);
} }
if(domWidth > document.documentElement.clientWidth){ if (domWidth > document.documentElement.clientWidth) {
let scale = document.documentElement.clientWidth / domWidth; let scale = document.documentElement.clientWidth / domWidth;
domWidth = Math.floor(document.documentElement.clientWidth); domWidth = Math.floor(document.documentElement.clientWidth);
domHeight = Math.floor(domHeight * scale); domHeight = Math.floor(domHeight * scale);
@ -124,46 +137,38 @@ export default defineComponent({
onMounted(() => { onMounted(() => {
if (props.src) { if (props.src) {
checkPdfLib().then(init).catch(e=>{ checkPdfLib().then(init).catch(e => {
console.warn(e); console.warn(e);
}); });
} }
}); });
watch(() => props.src, () => { watch(() => props.src, () => {
checkPdfLib().then(init).catch(e=>{ checkPdfLib().then(init).catch(e => {
console.warn(e); console.warn(e);
}); });
}); });
function save(fileName){ function save(fileName) {
pdfDocument && pdfDocument._transport && pdfDocument._transport.getData().then(fileData=>{ pdfDocument && pdfDocument._transport && pdfDocument._transport.getData().then(fileData => {
downloadFile(fileName || `vue-office-pdf-${new Date().getTime()}.pdf`,fileData.buffer); downloadFile(fileName || `vue-office-pdf-${new Date().getTime()}.pdf`, fileData.buffer);
}); });
} }
return { return {
rootRef, rootRef,
numPages, numPages,
save save,
onScrollPdf
}; };
} }
}); });
</script> </script>
<template> <template>
<div class="vue-office-pdf" ref="vue-office-pdf" style="text-align: center;overflow-y: auto;"> <div class="vue-office-pdf" ref="vue-office-pdf" style="text-align: center;overflow-y: auto;" @scroll="onScrollPdf">
<div <div v-if="numPages" class="vue-office-pdf-wrapper" style="background: gray; padding: 30px 0;position: relative;">
v-if="numPages" <canvas v-for="page in numPages" ref="rootRef" :key="page" style="width:100%" />
class="vue-office-pdf-wrapper"
style="background: gray; padding: 30px 0;position: relative;">
<canvas
v-for="page in numPages"
ref="rootRef"
:key="page"
style="width:100%"
/>
</div> </div>
</div> </div>
</template> </template>
<style lang="less"> <style lang="less">
</style> </style>