当前位置: 首页 > ai >正文

vue3: pdf.js5.2.133 using typescript

npm install pdfjs-dist@5.2.133

项目结构:

<!--* @creater: geovindu* @since: 2025-05-09 21:56:20* @LastAuthor: geovindu* @lastTime: 2025-05-09 22:12:17* @文件相对于项目的路径: \jsstudy\vuepdfpreview\comonents\pdfjs.vue* @message: geovindu* @IDE: vscode* @Development: node.js 20, vuejs3.0* @package:* @ISO: windows10* @database: mysql 8.0 sql server 2019 postgresSQL 16* Copyright (c) 2025 by geovindu email:geovindu@163.com, All Rights Reserved.
-->
<template><div class="pdf-container"><div v-if="loading" class="text-center py-8">加载中...</div><div v-else-if="error" class="text-center py-8 text-red-500">{{ error }}</div><div v-else><!-- 控制工具栏 --><div class="flex justify-between items-center mb-4"><div class="flex space-x-2"><button @click="zoomIn" class="px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600"><i class="fa fa-search-plus mr-1"></i> 放大</button><button @click="zoomOut" class="px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600"><i class="fa fa-search-minus mr-1"></i> 缩小</button><button @click="downloadPDF" class="px-3 py-1 bg-green-500 text-white rounded hover:bg-green-600"><i class="fa fa-download mr-1"></i> 下载文档</button></div><div class="text-center">缩放比例: {{ Math.round(scale * 100) }}%</div></div><!-- PDF 容器 --><div id="pdf-container" class="w-full h-[600px] border border-gray-300 overflow-auto"><canvas ref="pdfCanvas"></canvas></div><!-- 页码控制 --><div class="mt-4 text-center"><button @click="firstPage" :disabled="currentPage <= 1" class="px-3 py-1 bg-gray-200 rounded hover:bg-gray-300 mx-1">第一页</button><button @click="prevPage" :disabled="currentPage <= 1" class="px-3 py-1 bg-gray-200 rounded hover:bg-gray-300 mx-1">上一页</button><span class="mx-3">第 {{ currentPage }} / {{ totalPages }} 页</span><button @click="nextPage" :disabled="currentPage >= totalPages" class="px-3 py-1 bg-gray-200 rounded hover:bg-gray-300 mx-1">下一页</button><button @click="lastPage" :disabled="currentPage >= totalPages" class="px-3 py-1 bg-gray-200 rounded hover:bg-gray-300 mx-1">最后一页</button></div></div></div></template><script setup>import { ref, onMounted, reactive } from 'vue';import * as pdfjsLib from 'pdfjs-dist';// 设置 worker 路径//pdfjsLib.GlobalWorkerOptions.workerSrc = '/pdfjs/pdf.worker.mjs';// 动态解析worker路径,确保使用.mjs文件
pdfjsLib.GlobalWorkerOptions.workerSrc = new URL('pdfjs-dist/build/pdf.worker.mjs',import.meta.url
).toString();const props = defineProps({pdfUrl: { type: String, required: true }});const pdfCanvas = ref(null);const loading = ref(true);const error = ref('');const currentPage = ref(1);const totalPages = ref(0);const scale = ref(1.0);let pdfDoc = null;const renderPage = async (num) => {try {const page = await pdfDoc.getPage(num);const viewport = page.getViewport({ scale: scale.value });// 设置 canvas 尺寸pdfCanvas.value.width = viewport.width;pdfCanvas.value.height = viewport.height;// 渲染页面const renderContext = {canvasContext: pdfCanvas.value.getContext('2d'),viewport: viewport};await page.render(renderContext).promise;currentPage.value = num;} catch (err) {console.error('渲染页面失败:', err);error.value = `渲染失败: ${err.message}`;}};const prevPage = () => {if (currentPage.value > 1) {renderPage(currentPage.value - 1);}};const nextPage = () => {if (currentPage.value < totalPages.value) {renderPage(currentPage.value + 1);}};const firstPage = () => {if (currentPage.value !== 1) {renderPage(1);}};const lastPage = () => {if (currentPage.value !== totalPages.value) {renderPage(totalPages.value);}};const zoomIn = () => {scale.value = Math.min(scale.value + 0.1, 3.0); // 最大缩放 300%renderPage(currentPage.value);};const zoomOut = () => {scale.value = Math.max(scale.value - 0.1, 0.5); // 最小缩放 50%renderPage(currentPage.value);};const downloadPDF = () => {try {const link = document.createElement('a');link.href = props.pdfUrl;link.download = props.pdfUrl.split('/').pop() || 'document.pdf';link.click();} catch (e) {console.error('下载失败:', e);error.value = '下载失败,请尝试右键另存为';window.open(props.pdfUrl, '_blank');}};onMounted(async () => {try {// 加载 PDFconst loadingTask = pdfjsLib.getDocument(props.pdfUrl);pdfDoc = await loadingTask.promise;totalPages.value = pdfDoc.numPages;// 渲染第一页renderPage(1);loading.value = false;} catch (err) {console.error('加载 PDF 失败:', err);error.value = `加载失败: ${err.message}`;loading.value = false;}});</script><style scoped>.pdf-container {max-width: 1000px;margin: 0 auto;}#pdf-container canvas {max-width: 100%;display: block;margin: 0 auto;}</style>
<!--* @creater: geovindu* @since: 2025-05-09 21:56:20* @LastAuthor: geovindu* @lastTime: 2025-05-09 22:12:17* @文件相对于项目的路径: \jsstudy\vuepdfpreview\src\App.vue* @message: geovindu* @IDE: vscode* @Development: node.js 20, vuejs3.0* @package:* @ISO: windows10* @database: mysql 8.0 sql server 2019 postgresSQL 16* Copyright (c) 2025 by geovindu email:geovindu@163.com, All Rights Reserved.
--><template>
<div class="pdf-container"><PDFView :pdfUrl="pdfUrl" v-if="pdfUrl" /><div v-else >加载中...</div>
</div><div><a href="https://vite.dev" target="_blank"><img src="/vite.svg" class="logo" alt="Vite logo" /></a><a href="https://vuejs.org/" target="_blank"><img src="./assets/vue.svg" class="logo vue" alt="Vue logo" /></a></div><HelloWorld msg="Vite + Vue" />
</template>
<script setup lang="ts">
import HelloWorld from './components/HelloWorld.vue'
//import PDFView from './components/vuepdfjs.vue' // 可以//import PDFView from './components/pdfPreview.vue' // 可以import PDFView from "./components/pdfjs.vue"   //可以//import pdfUrl from "./pdfs/01.pdf"const pdfUrl = "./pdfs/09.pdf"</script>
<style scoped>
.logo {height: 6em;padding: 1.5em;will-change: filter;transition: filter 300ms;
}
.logo:hover {filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {filter: drop-shadow(0 0 2em #42b883aa);
}
</style>

输出:

http://www.xdnf.cn/news/4908.html

相关文章:

  • Windows 10 无法启动或黑屏的修复指南(适用于更新失败或磁盘故障)
  • javascript 补充的一些知识点
  • HarmonyOS学习——ArkTS与TS的关系
  • ArcScroll: 弧形滑动控件
  • 初等数论--欧拉函数积性的证明
  • Uniapp Android/IOS 获取手机通讯录
  • 【Linux】自定义shell的编写
  • vllm的技术核心、安装流程和使用教程,以及注意事项
  • 自主独立思考,帮我创造新的方法:vue3 script setup语法中,组件传递值我觉得有些复杂,帮我创造一种简单的方法容易写的方法?
  • 使用Java实现HTTP协议服务:从自定义服务器到内置工具
  • 数据加密方式(对称加密/非对称加密 /数字签名/证书)
  • vue项目的创建
  • 字符串---Spring字符串基本处理
  • 耳机插进电脑只有一边有声音怎么办 解决方法分享
  • 第十六届蓝桥杯B组第二题
  • 什么是分布式光伏系统?屋顶分布式光伏如何并网?
  • 高质量老年生活:从主动健康管理到预防医学的社会价值
  • 在 Spring Boot 中选择合适的 HTTP 客户端
  • 2025年社交APP安全防御指南:抵御DDoS与CC攻击的实战策略
  • NLP基础
  • 支付宝 SEO 优化:提升小程序曝光与流量的完整指南
  • Kotlin中Lambda表达式和匿名函数的区别
  • RabbitMQ消息的重复消费问题如何解决?
  • jenkins 启动报错
  • 从粗放管控到数字治能——安科瑞智能监测系统助力污水厂能耗下降15%+
  • 如何通过C# 获取Excel单元格的数据类型
  • YOLO算法的基本介绍
  • 【react组件】矩形框选小组件,鼠标左键选中 div,键盘 ESC 清空
  • 【Axios】解决Axios下载二进制文件返回空对象的问题
  • 高性能Python Web 框架--FastAPI 学习「基础 → 进阶 → 生产级」