admin管理员组

文章数量:1649178

环境说明:vue3 + vite + antdesignVue,使用pdfjs-dist插件,版本为2.16.105

提示:pdfjs-dist版本>3时,node版本需要>18

1、在vite.config.js中添加vite-plugin-top-level-await插件

npm install vite-plugin-top-level-await --save -dev

import topLevelAwait from 'vite-plugin-top-level-await'

export default defineConfig({
    plugins: [topLevelAwait(),]
})

2、页面代码如下,支持滚动翻页、点击翻页、跳转页码

<template>
	<div class="dy-pdf-preview">
		<div v-if="pdfPagesNum === 0" class="loading">
			<a-spin size="large" />
		</div>
		<div v-if="pdfPagesNum > 0" class="pdf-preview-wrap" @scroll="pdfScroll">
			<div v-for="item in pdfPagesNum" :key="item" class="pdf-wrap">
				<canvas :id="`pdf_canvas_${item}`" style="width: 100%; height: 100%"></canvas>
			</div>
		</div>
		<div v-if="pdfPagesNum > 0" class="pdf-preview-footer">
			<div class="left">
				<div class="page">{{ currentPage }}/{{ pdfPagesNum }}</div>
				<div class="jump">
					跳转
					<a-input
						v-model:value="jumpPage"
						size="small"
						@blur="toPage(jumpPage)"
						@keyup.enter="toPage(jumpPage)"
					></a-input>
					页
				</div>
			</div>
			<div class="right">
				<a-button type="primary" :disabled="currentPage <= 1" @click="prevPage">上一页</a-button>
				<a-button type="primary" :disabled="currentPage >= pdfPagesNum" @click="nextPage"
					>下一页</a-button
				>
			</div>
		</div>
	</div>
</template>

<script setup lang="ts">
const props = defineProps({
	// 文件id
	fileId: String,
})

const pdfPagesNum = ref(0)
const currentPage = ref(1)
const jumpPage = ref(1)
const canvasHeight = ref(0)

function show() {
	pdfPagesNum.value = 0
	xxx.filePreview(props.fileId).then(res => {
		handlePdf(res.data)
	})
}
// 处理pdf
function handlePdf(file) {
	let reader = new FileReader()
	reader.readAsDataURL(file) //将文件读取为 DataURL
	reader.onload = async function () {
		//文件读取成功完成时触发
		const pdfjs = await import('pdfjs-dist')
		pdfjs.GlobalWorkerOptions.workerSrc = new URL(
			'pdfjs-dist/build/pdf.worker.js', //pdfjs-dist版本>4时,路径为pdfjs-dist/build/pdf.worker.mjs,
			import.meta.url
		).href
		const loadingTask = pdfjs.getDocument(reader.result)
		loadingTask.promise.then(pdf => {
			pdfPagesNum.value = pdf.numPages
			// 等待dom渲染
			nextTick(() => {
				//处理
				for (let i = 1; i <= pdf.numPages; i++) {
					pdf.getPage(i).then(page => {
						const canvas = document.getElementById('pdf_canvas_' + i)
						const ctx = canvas.getContext('2d')
						const viewport = page.getViewport({ scale: 3 })
						// 画布大小,默认值是width:300px,height:150px
						canvas.height = viewport.height
						canvas.width = viewport.width
						page.render({
							canvasContext: ctx,
							viewport,
						})
					})
				}
			})
		})
	}
}
// 滚动事件
function pdfScroll() {
	if (pdfPagesNum.value > 0) {
		nextTick(() => {
			const firstCanvas = document.querySelector('.pdf-wrap')
			if (canvasHeight.value !== firstCanvas.clientHeight) {
				canvasHeight.value = firstCanvas.clientHeight
			}
			canvasHeight.value = firstCanvas.clientHeight
		})
	}
	let pdfWrap = document.querySelector('.pdf-preview-wrap')
	for (let i = 0; i < pdfPagesNum.value; i++) {
		// 在滚动时,根据当前滚动距离和每页滚动的临界距离相比较,判断当前是第几页
		if ((pdfWrap.scrollTop + canvasHeight.value * 0.1) / canvasHeight.value < i + 1) {
			if (currentPage.value != i + 1) {
				currentPage.value = i + 1
			}
			break
		}
	}
}

// 跳转
function toPage(val) {
	if (isNaN(Number(val)) || !val || Number(val) < 1) {
		jumpPage.value = 1
		currentPage.value = 1
	} else if (Number(val) > pdfPagesNum.value) {
		jumpPage.value = pdfPagesNum.value
		currentPage.value = pdfPagesNum.value
	} else {
		currentPage.value = Number(val)
	}
	currentPageChange()
}
// 上一页
function prevPage() {
	if (currentPage.value > 1) {
		currentPage.value--
		currentPageChange()
	}
}

// 下一页
function nextPage() {
	if (currentPage.value < pdfPagesNum.value) {
		currentPage.value++
		currentPageChange()
	}
}

// 页码切换事件
function currentPageChange() {
	let pdfWrap = document.querySelector('.pdf-preview-wrap')
	pdfWrap.scrollTop = canvasHeight.value * (currentPage.value - 1)
}

defineExpose({
	show,
})
</script>

<style lang="scss" scoped>
.dy-pdf-preview {
	width: 100%;
	height: 100%;
	.loading {
		width: 100%;
		height: 500px;
		display: flex;
		justify-content: center;
		align-items: center;
	}
	.pdf-preview-wrap {
		width: 100%;
		height: calc(100% - 40px);
		overflow-y: auto;
		.pdf-wrap {
			width: 100%;
			position: relative;
		}
	}
	.pdf-preview-footer {
		position: absolute;
		width: calc(100% - 36px);
		height: 52px;
		bottom: 3px;
		border-top: 1px solid #e3e8ef;
		display: flex;
		align-items: center;
		justify-content: space-between;
		.left {
			display: flex;
			align-items: center;
			.page {
				margin-right: 15px;
			}
			.jump {
				display: flex;
				align-items: center;
				.ant-input {
					width: 38px;
					margin: 0 5px 2px 5px;
				}
			}
		}
		.right {
			width: 160px;
			display: flex;
			align-items: center;
			justify-content: space-between;
		}
	}
}
</style>

本文标签: 翻页vitepdfjsPDFdist