Vue 3 中使用 vue - pdf - embed + vue3 - pdfjs 在线预览 PDF

打印 上一主题 下一主题

主题 975|帖子 975|积分 2925



在很多 Web 应用步调中,需要实现 PDF 文件的在线预览功能。Vue 3 作为流行的前端框架,配合 vue - pdf - embed 和 vue3 - pdfjs 库,可以轻松实现这一需求。本文将详细介绍如安在 Vue 3 项目中使用这两个库举行 PDF 在线预览。
 完整代码实现及演示效果请参考开源项目:vue3-pc-template
一、环境预备

确保你已经创建了一个 Vue 3 项目,并且安装了相关依赖。如果没有安装 vue - pdf - embed 和 vue3 - pdfjs,可以通过以下命令举行安装:
  1. npm install vue - pdf - embed vue3 - pdfjs
复制代码
二、代码实现

(一)父组件中使用

  1. <template>
  2. <div class="pdf-container">
  3. <PDFView :pdfUrl="jsPdf" />
  4. </div>
  5. </template>
  6. <script setup>
  7. import PDFView from "@/components/PdfPreview/index.vue
  8. ";
  9. import jsPdf from "/pdf/test.pdf"; // 本地地址
  10. // const jsPdf = 'http://localhost/test.pdf' // 线上地址也可,但需要注意跨域问题
  11. </script>
  12. <style scoped>
  13. .pdf-container {
  14. overflow: auto;
  15. }
  16. </style>
复制代码
1、 template部分

在<template>中,创建了一个div容器,类名为pdf - container,用于包裹 PDF 预览组件PDFView。并通过:pdfUrl属性将jsPdf通报给子组件PDFView。
2、 script部分

引入PDFView组件,同时界说了jsPdf变量,它可以是本地 PDF 文件路径(如/pdf/test.pdf),也可以是线上地点(但要注意跨域问题)。
3、 style部分

给pdf - container添加overflow: auto样式,以便在内容超出容器巨细时出现滚动条。
(二)将实现逻辑封装成子组件

  1. @/components/PdfPreview/index.vue
复制代码
  1. <template>
  2. <div class="pdf-preview">
  3. <div id="page - view" :style="{
  4. position: 'absolute',
  5. top: '50%',
  6. left: '50%',
  7. transform: `translate(-50%, -50%) scale(${state.scale})`,
  8. width: '100%',
  9. height: `${pageHeight}`,
  10. }">
  11. <vue - pdf - embed :source="state.source" :page="state.pageNum" textLayer />
  12. </div>
  13. </div>
  14. <div class="page - tool">
  15. <div class="page - tool - item" @click="lastPage">上一页</div>
  16. <div class="page - tool - item" @click="nextPage">下一页</div>
  17. <div class="page - tool - item">{{ state.pageNum }}/{{ state.numPages }}</div>
  18. <div class="page - tool - item" @click="pageZoomOut">放大</div>
  19. <div class="page - tool - item" @click="pageZoomIn">缩小</div>
  20. </div>
  21. </template>
  22. <script setup lang="ts">
  23. import { reactive, onMounted, ref } from "vue";
  24. import VuePdfEmbed from "vue - pdf - embed";
  25. import { createLoadingTask } from "vue3 - pdfjs";
  26. const props = defineProps({
  27. pdfUrl: {
  28. type: String,
  29. required: true,
  30. },
  31. });
  32. const pageHeight = ref('100%');
  33. const state = reactive({
  34. source: props.pdfUrl, //预览pdf文件地址
  35. pageNum: 1, //当前页面
  36. scale: 1, // 缩放比例
  37. numPages: 0, // 总页数
  38. });
  39. function lastPage() {
  40. if (state.pageNum > 1) {
  41. state.pageNum -= 1;
  42. }
  43. }
  44. function nextPage() {
  45. if (state.pageNum < state.numPages) {
  46. state.pageNum += 1;
  47. }
  48. }
  49. function pageZoomOut() {
  50. if (state.scale < 2) {
  51. state.scale += 0.1;
  52. pageHeight.value = (parseInt(pageHeight.value) - 5.0) + '%';
  53. }
  54. }
  55. function pageZoomIn() {
  56. if (state.scale > 1) {
  57. state.scale -= 0.1;
  58. pageHeight.value = (parseInt(pageHeight.value) + 5.0) + '%';
  59. }
  60. }
  61. onMounted(() => {
  62. const loadingTask = createLoadingTask(state.source);
  63. loadingTask.promise.then((pdf: { numPages: number }) => {
  64. state.numPages = pdf.numPages;
  65. });
  66. });
  67. </script>
  68. <style lang="css" scoped>
  69. .pdf-preview {
  70. position: relative;
  71. height: 100vh;
  72. padding: 20px 0;
  73. box-sizing: border-box;
  74. background-color: e9e9e9;
  75. }
  76. .pdf-wrap {
  77. overflow-y: auto;
  78. }
  79. .vue - pdf - embed {
  80. text-align: center;
  81. width: 515px;
  82. border: 1px solid #e5e5e5;
  83. margin: 0 auto;
  84. box-sizing: border-box;
  85. }
  86. .page - tool {
  87. position: absolute;
  88. bottom: 35px;
  89. padding-left: 15px;
  90. padding-right: 15px;
  91. display: flex;
  92. align-items: center;
  93. background: rgb(66, 66, 66);
  94. color: white;
  95. border-radius: 19px;
  96. z-index: 100;
  97. cursor: pointer;
  98. margin-left: 50%;
  99. transform: translateX(-50%);
  100. }
  101. .page - tool - item {
  102. padding: 8px 15px;
  103. padding-left: 10px;
  104. cursor: pointer;
  105. }
  106. </style>
复制代码
1、 template部分



  • 创建了一个div容器,类名为pdf - preview,作为整体的预览区域,设置了相对定位和一些基本样式。
  • 在pdf - preview内部,有一个div,id为page - view,通过:style绑定动态样式,实现居中显示和缩放效果。在这个div内部,使用vue - pdf - embed组件,通过:source属性通报 PDF 文件地点,:page属性通报当前显示的页码,并启用textLayer。
  • 下方还有一个div,类名为page - tool,用于显示页面切换和缩放的工具按钮。每个按钮通过@click绑定相应的方法。
2、 script部分



  • 引入 Vue 的reactive、onMounted、ref等函数,以及vue - pdf - embed和vue3 - pdfjs中的createLoadingTask。
  • 通过defineProps界说接收父组件通报的pdfUrl属性,并且设置为必填。
  • 使用ref界说pageHeight变量,初始值为100%,用于控制预览区域的高度。
  • 使用reactive界说state对象,包含source(PDF 文件地点)、pageNum(当前页码)、scale(缩放比例)、numPages(总页数)等属性。
  • 界说了lastPage、nextPage、pageZoomOut、pageZoomIn等方法,分别用于上一页、下一页、放大、缩小的功能实现。
  • 在onMounted钩子函数中,通过createLoadingTask创建加载任务,获取 PDF 文件的总页数并更新state.numPages。
3、 样式部分



  • 给pdf - preview设置配景致、高度、内边距等样式。
  • 给vue - pdf - embed设置居中显示、边框、宽度等样式。
  • 给page - tool设置绝对定位、配景致、圆角、水平居中对齐等样式,给page - tool - item设置内边距和鼠标指针样式。
三、注意事项

1、 跨域问题

如果使用线上地点,需要确保服务器端设置了精确的跨域策略,否则会出现跨域请求失败的问题。可以通过在服务器端配置 CORS(跨域资源共享)来办理。
2、 文件路径

确保本地 PDF 文件路径精确,并且在打包和部署时,文件可以大概精确被访问到。

完整代码实现请参考开源项目:vue3-pc-template
   欢迎 Star 和 Fork 项目,一起构建更完善的权限管理体系!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

羊蹓狼

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表