pdfViewExample.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. <template>
  2. <div class="pdf-view-example j-contanter">
  3. <div class="j-main">
  4. <PDF
  5. v-if="pdfUrl"
  6. :useLoading="false"
  7. :usePagination="false"
  8. :url="pdfUrl"
  9. ></PDF>
  10. </div>
  11. <div v-if="!getUserId" class="j-footer">
  12. <!-- /jyapp/free/login?url=/jy_mobile/order/create/creditreport&activity=bidCreditReportPreview -->
  13. <AdSingle
  14. ad="app-credit-report-sample"
  15. :show-tag="false"
  16. :show-close-icon="false"
  17. class="adsense-container"
  18. />
  19. </div>
  20. </div>
  21. </template>
  22. <script>
  23. import { mapGetters } from 'vuex'
  24. import AdSingle from '@/components/ad/Ad'
  25. import { getAssetsFile } from '@/utils'
  26. import PDF from '@/views/article/components/PDF.vue'
  27. export default {
  28. name: 'PdfViewExample',
  29. components: {
  30. AdSingle,
  31. PDF
  32. },
  33. data() {
  34. return {
  35. pdfUrl: '',
  36. pdf: null,
  37. totalPages: 0,
  38. currentPage: 1, // 新增
  39. batchSize: 5, // 新增
  40. config: {
  41. PAGE_TO_VIEW: 0,
  42. SCALE: 1.0,
  43. CMAP_URL:
  44. 'https://cdn-common.jianyu360.com/cdn/lib/pdfjs-dist/2.1.266/cmaps/',
  45. CMAP_PACKED: true,
  46. workerSrc:
  47. 'https://cdn-common.jianyu360.com/cdn/lib/pdfjs-dist/2.1.266/build/pdf.worker.min.js'
  48. }
  49. }
  50. },
  51. computed: {
  52. ...mapGetters('user', ['getUserId'])
  53. },
  54. created() {
  55. this.$toast.loading('加载中...')
  56. const { pdfUrl } = this.$route.query
  57. if (pdfUrl) {
  58. this.pdfUrl = decodeURIComponent(pdfUrl)
  59. } else {
  60. const pdfAssets = getAssetsFile('example-min.pdf')
  61. // this.pdfUrl = 'https://cdn-common.jianyu360.cn/cdn/assets/file/example.pdf'
  62. this.pdfUrl = pdfAssets
  63. }
  64. },
  65. mounted() {
  66. // const container = document.getElementById('pdf-view-container')
  67. //
  68. // this.loadPdf(this.pdfUrl, container)
  69. // // 监听窗口的 resize 事件,实现自适应效果
  70. // window.addEventListener('resize', () => {
  71. // container.innerHTML = ''
  72. // this.loadPdf(this.pdfUrl, container)
  73. // })
  74. },
  75. methods: {
  76. async loadPdf(pdfUrl, container) {
  77. console.log('pdfUrl', pdfUrl)
  78. try {
  79. pdfjsLib.GlobalWorkerOptions.workerSrc = this.config.workerSrc
  80. const loadingTask = pdfjsLib.getDocument({
  81. url: pdfUrl,
  82. cMapUrl: this.config.CMAP_URL,
  83. cMapPacked: this.config.CMAP_PACKED,
  84. disableRange: true,
  85. disableAutoFetch: false, // 启动自动分块加载
  86. // 添加缓存头
  87. httpHeaders: {
  88. 'Cache-Control': 'max-age=3600' // 缓存 1 小时
  89. },
  90. // 增加网络请求超时时间,避免因网络问题导致加载失败
  91. timeout: 30000,
  92. // 减少初始加载的字节数,提高初始加载速度
  93. initialDataSize: 1024 * 1024
  94. })
  95. this.pdf = await loadingTask.promise
  96. this.totalPages = this.pdf.numPages
  97. this.currentPage = 1
  98. this.batchSize = 5 // 新增
  99. await this.loadBatchPages(container) // 新增
  100. this.$toast.clear()
  101. // 监听滚动事件
  102. container.addEventListener('scroll', () => this.handleScroll(container))
  103. } catch (error) {
  104. console.error('Error loading PDF:', error)
  105. }
  106. },
  107. async loadBatchPages(container) {
  108. // 加载当前页码开始的连续多页,这里以5页为例
  109. // 分批加载,从当前页码开始,最多加载5页
  110. const endPage = Math.min(
  111. this.currentPage + this.batchSize - 1,
  112. this.totalPages
  113. )
  114. for (let pageNum = this.currentPage; pageNum <= endPage; pageNum++) {
  115. const page = await this.pdf.getPage(pageNum)
  116. const viewport = page.getViewport({ scale: this.calculateScale(page) })
  117. const canvas = document.createElement('canvas')
  118. const ctx = canvas.getContext('2d')
  119. canvas.height = viewport.height
  120. canvas.width = viewport.width
  121. container.appendChild(canvas)
  122. await page.render({
  123. canvasContext: ctx,
  124. viewport
  125. }).promise
  126. }
  127. this.currentPage = endPage + 1 // 更新当前页码
  128. },
  129. handleScroll(container) {
  130. const { scrollTop, scrollHeight, clientHeight } = container
  131. if (scrollTop + clientHeight >= scrollHeight - 100) {
  132. // 当滚动到底部附近时
  133. if (this.currentPage <= this.totalPages) {
  134. this.loadBatchPages(container)
  135. }
  136. }
  137. },
  138. // 计算缩放比例以适应容器宽度
  139. calculateScale(page) {
  140. const containerWidth =
  141. document.getElementById('pdf-view-container').clientWidth
  142. const viewport = page.getViewport({ scale: 1 })
  143. // 增加一个倍数来提高清晰度,例如 1.5
  144. return (containerWidth / viewport.width) * 3
  145. }
  146. }
  147. }
  148. </script>
  149. <style lang="scss" scoped>
  150. .pdf-view-example {
  151. ::v-deep {
  152. .pdf-box {
  153. height: 100%;
  154. }
  155. .pdfjs {
  156. padding-top: 0;
  157. }
  158. .pdfViewer {
  159. padding: 0;
  160. }
  161. }
  162. }
  163. </style>