vue3+vite在线预览pdf
记录原因:公司任务有此需求,网上查找资料发现全是复制粘贴同一篇的,而且有报错structuredClone is not defined

效果图:
完整代码:
1、pdfPreview.vue
1 <template> 2 <div class="pdf-preview"> 3 <div class="pdf-wrap"> 4 <vue-pdf-embed :source="state.source" :style="scale" class="vue-pdf-embed" :page="state.pageNum" /> 5 </div> 6 <div class="page-tool"> 7 <div class="page-tool-item" @click="lastPage()">上一页</div> 8 <div class="page-tool-item" @click="nextPage()">下一页</div> 9 <div class="page-tool-item">{{state.pageNum}}/{{state.numPages}}</div> 10 <div class="page-tool-item" @click="pageZoomOut()">放大</div> 11 <div class="page-tool-item" @click="pageZoomIn()">缩小</div> 12 <div class="page-tool-item" @click="$emit('close')">关闭</div> 13 </div> 14 </div> 15 </template> 16 <script setup lang="ts"> 17 import VuePdfEmbed from "vue-pdf-embed"; 18 //import { createLoadingTask } from "vue3-pdfjs/esm/vue-pdf.js"; 19 import * as pdfjsLib from "pdfjs-dist"; 20 import { reactive, onMounted, computed } from "vue"; 21 22 const props = defineProps({ 23 pdfUrl: { 24 type: String, 25 required: true 26 } 27 }) 28 29 30 const state = reactive({ 31 source: props.pdfUrl, //预览pdf文件地址 32 pageNum: 1, //当前页面 33 scale: 1, // 缩放比例 34 numPages: 0, // 总页数 35 }); 36 const scale = computed(() => `transform:scale(${state.scale})`) 37 function lastPage() { 38 if (state.pageNum > 1) { 39 state.pageNum -= 1; 40 } 41 } 42 function nextPage() { 43 if (state.pageNum < state.numPages) { 44 state.pageNum += 1; 45 } 46 } 47 function pageZoomOut() { 48 if (state.scale < 2) { 49 state.scale += 0.1; 50 } 51 } 52 function pageZoomIn() { 53 if (state.scale > 0.8) { 54 state.scale -= 0.1; 55 } 56 } 57 onMounted(() => { 58 pdfjsLib.GlobalWorkerOptions.workerSrc = "./pdf.worker.js"; 59 const loadingTask = pdfjsLib.getDocument(state.source); 60 loadingTask.promise.then((pdf) => { 61 state.numPages = pdf.numPages; 62 }); 63 }); 64 65 </script> 66 <style lang="css" scoped> 67 .pdf-preview { 68 position: fixed; 69 height: 100vh; 70 width: 100vw; 71 padding: 20px 0; 72 box-sizing: border-box; 73 background-color: #e9e9e9; 74 left: 0; 75 top: 0; 76 z-index: 99999999; 77 overflow-y: auto; 78 } 79 80 .pdf-wrap { 81 overflow-y: auto; 82 } 83 84 .vue-pdf-embed { 85 text-align: center; 86 width: 60vw; 87 border: 1px solid #e5e5e5; 88 margin: 0 auto; 89 box-sizing: border-box; 90 } 91 92 .page-tool { 93 position: fixed; 94 bottom: 35px; 95 padding-left: 15px; 96 padding-right: 15px; 97 display: flex; 98 align-items: center; 99 background: rgb(66, 66, 66); 100 border-radius: 19px; 101 z-index: 100; 102 cursor: pointer; 103 margin-left: 50%; 104 transform: translateX(-50%); 105 } 106 107 .page-tool-item { 108 padding: 8px 15px; 109 padding-left: 10px; 110 cursor: pointer; 111 color: #fff !important; 112 } 113 </style>
2、引入方式:需要用到该组件的地方可以直接引入使用
import pdfPreview from './components/pdfPreview.vue';
<pdfPreview v-if="store.state.pdfUrl" :pdfUrl="store.state.pdfUrl" @close="store.state.pdfUrl = null" />
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端