vue3 + vite + pdfjs-dist 实现pdf预览,支持翻页和滚动翻页

环境说明: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>

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,您的问题是关于如何使用Vue3和Vite以及Kbone来实现Web和小程序共用代码。 首先,Vue3和Vite是一个非常好的组合,可以提供快速的开发和优化,而Kbone则是一个基于Vue和微信小程序的跨端开发框架,可以使得我们的代码在Web和小程序之间共用。 以下是实现的步骤: 1. 安装Vue3和Vite 可以通过npm安装最新版本的VueVite: ``` npm install vue@next vite --save-dev ``` 2. 安装Kbone 使用以下命令安装Kbone: ``` npm install @weixin/kbone-cli --save-dev ``` 3. 创建Kbone项目 在命令行中输入以下命令创建Kbone项目: ``` npx kbone init my-project ``` 这将创建一个名为“my-project”的Kbone项目。 4. 配置Vite 在Kbone项目根目录下创建一个Vite配置文件vite.config.js,并添加以下代码: ```javascript const { name } = require('./package.json') module.exports = { build: { rollupOptions: { input: { main: 'src/main.js' }, output: { format: 'esm', dir: 'dist' } }, lib: { entry: 'src/main.js', name } } } ``` 这将告诉Vite将我们的代码打包为一个库。 5. 编写代码 在Kbone项目的src目录下编写我们的代码,可以使用Vue3的语法。 6. 将代码导出为小程序代码 在命令行中输入以下命令将Kbone项目导出为小程序代码: ``` npm run build:mp ``` 7. 在小程序中使用代码 将导出的小程序代码上传到微信小程序开发者工具中即可在小程序中使用我们的代码。 8. 在Web中使用代码 在我们的Web项目中,我们可以使用以下代码来引入我们的Kbone代码: ```javascript import { createApp } from 'vue' import App from 'my-project' import 'my-project/dist/my-project.css' createApp(App).mount('#app') ``` 这将在我们的Web项目中使用我们的Kbone代码。 综上所述,通过使用Vue3和Vite以及Kbone框架,我们可以在Web和小程序之间共用代码,提高开发效率和代码复用性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值