PdfViewer.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. <template>
  2. <div class="vue-pdf" @scroll="onScroll" ref="myDiv">
  3. <vue-pdf-embed :source="testpdf1" ref="vuePdfRef" :style="scaleFun" class="vue-pdf-cs" @loaded="onPdfLoaded" :renderPageNumber="true" />
  4. </div>
  5. <div class="page-tool">
  6. <div class="page-tool-item" @click="lastPage">上一页</div>
  7. <div class="page-tool-item" @click="nextPage">下一页</div>
  8. <div class="page-tool-item" @click="pageZoomOut">放大</div>
  9. <div class="page-tool-item" @click="pageZoomIn">缩小</div>
  10. <div class="page-tool-item" @click="PDFPrint">打印</div>
  11. <div class="page-tool-item" @click="PDFDownload">下载</div>
  12. </div>
  13. <div class="page-tool2">
  14. <div class="page-tool-item" @click="lastPage">{{scaleData.pageNum}}/{{scaleData.numPages}}</div>
  15. </div>
  16. </template>
  17. <script setup lang="ts">
  18. import VuePdfEmbed from 'vue-pdf-embed';
  19. import testpdf1 from '../../assets/testpdf.pdf';
  20. import {computed, onMounted, reactive, ref} from "vue";
  21. // 实现pdf缩放
  22. const scaleFun = computed(() => {
  23. return {
  24. transform: `scale(${scaleData.scale})`,
  25. transition: 'all 0.3s',
  26. transformOrigin: 'top'
  27. };
  28. });
  29. const scaleData = reactive({
  30. scale: 0.6, // 缩放比例
  31. scaleNum: 0.1, // 滚轮缩放比例
  32. scaleMax: 100, // 最大缩放比例
  33. scaleMin: 0.1, // 最小缩放比例
  34. scaleBtn: 0.4, // 缩放按钮缩放比例
  35. pageNum: 1, // 当前页面
  36. url: 'http://www.fao.fudan.edu.cn/_upload/article/files/f5/53/8b40af524563b9b60049899b2dd3/c9a205b4-4188-4af3-863e-bc4e56872e33.pdf',
  37. numPages: 0
  38. });
  39. const vuePdfRef = ref<InstanceType<typeof VuePdfEmbed> | null>(null);
  40. const myDiv = ref(null);
  41. const lastPage = () => {
  42. if (scaleData.pageNum > 1) {
  43. scaleData.pageNum--
  44. scrollToPage()
  45. }
  46. };
  47. const nextPage = () => {
  48. if (scaleData.pageNum < scaleData.numPages) {
  49. scaleData.pageNum++
  50. scrollToPage()
  51. }
  52. };
  53. const pageZoomOut = () => {
  54. if (scaleData.scale < scaleData.scaleMax) {
  55. scaleData.scale += scaleData.scaleNum;
  56. }
  57. };
  58. const pageZoomIn = () => {
  59. if (scaleData.scale > scaleData.scaleMin) {
  60. scaleData.scale -= scaleData.scaleNum;
  61. }
  62. };
  63. const PDFPrint = () => {
  64. vuePdfRef.value?.print(300, getPDFFileName(), true)
  65. };
  66. const PDFDownload = () => {
  67. vuePdfRef.value?.download(getPDFFileName())
  68. };
  69. const getPDFFileName = () => {
  70. const last_index= scaleData.url.lastIndexOf('/');
  71. return scaleData.url.slice(last_index+ 1);
  72. };
  73. const onPdfLoaded = (data: { numPages: number }) => {
  74. scaleData.numPages = data.numPages
  75. };
  76. const scrollToPage = () => {
  77. const pdfContainer = myDiv.value;
  78. const pageHeight = pdfContainer.scrollHeight / scaleData.numPages;
  79. const targetScrollPosition = (scaleData.pageNum-1) * pageHeight;
  80. pdfContainer.scrollTo({
  81. top: targetScrollPosition,
  82. behavior: 'smooth'
  83. });
  84. };
  85. const onScroll = () => {
  86. const pdfContainer = myDiv.value;
  87. const scrollTop = pdfContainer.scrollTop+100;
  88. const pageHeight = pdfContainer.scrollHeight / scaleData.numPages;
  89. const currentPage = Math.floor(scrollTop / pageHeight) + 1;
  90. scaleData.pageNum = currentPage;
  91. };
  92. </script>
  93. <style scoped>
  94. .page-tool2 {
  95. position: absolute;
  96. bottom: 18%;
  97. padding-left: 10px;
  98. padding-right: 10px;
  99. align-items: center;
  100. background: rgba(3, 67, 109, 0.075);
  101. color: rgba(2, 1, 41, 0.507);
  102. border-radius: 19px;
  103. z-index: 100;
  104. cursor: pointer;
  105. margin-left: 80%;
  106. margin-right:50px; /* 修改这里 */
  107. }
  108. .page-tool {
  109. position: absolute;
  110. bottom: 25%;
  111. padding-left: 15px;
  112. padding-right: 15px;
  113. align-items: center;
  114. background: rgba(3, 67, 109, 0.075);
  115. color: rgba(2, 1, 41, 0.507);
  116. border-radius: 19px;
  117. z-index: 100;
  118. cursor: pointer;
  119. margin-left: 80%;
  120. margin-right:50px; /* 修改这里 */
  121. }
  122. .page-tool-item {
  123. padding: 20px 15px;
  124. cursor: pointer;
  125. }
  126. .vue-pdf{
  127. margin: 0px auto;
  128. width: 100%;
  129. position: relative;
  130. overflow: auto;
  131. background: #e3e2e2;
  132. }
  133. .vue-pdf-cs{
  134. width: 100%;
  135. height: 100%;
  136. text-align: center;
  137. display: flex;
  138. flex-direction: column;
  139. gap: 20px;
  140. }
  141. </style>