加载中...

vue3使用pdfjs-dist

vue3使用pdfjs-dist

效果展示:

New Image

首先我的版本是:

 "vue": "^3.3.4",

 "vite": "^4.2.1",

"pdfjs-dist": "^4.0.379",

然后安装 :

npm i pdfjs-dist

如果遇到 报错:

Top-level await is not available in the configured target environment ("chrome87", "edge88", "es2020", "firefox78", "safari14" + 2 overrides) node_modules/pdfjs-dist/build/pdf.mjs:17349:53: 17349 │ /******/ __webpack_exports__ = globalThis.pdfjsLib = await (globalThis.pdfjsLibPromise = __webpack_exports__);

  • 原因:vite 不支持顶级的 async/await 语法,需要安装插件做兼容
  • 解决:vite.config.ts 安装并引入 topLevelAwait
  • npm install vite-plugin-top-level-await -D

    然后 找到对应位置:   // vite.config.ts 文件
    import topLevelAwait from ''vite-plugin-top-level-await''

    export default ({ mode }: any) => {
        return defineConfig({
            plugins: [
                topLevelAwait({
                    promiseExportName: ''__tla'',
                    promiseImportName: (i) => `__tla_${i}`
                })
            ],
        })
    }

具体完整实现代码:

pdf组件

  1. <template>
  2. <div class="pdf-container">
  3. <canvas v-for="pdfIndex in pdfPages" :id="`pdf-canvas-${pdfIndex}`" :key="pdfIndex" />
  4. </div>
  5. </template>
  6. <script setup lang="ts">
  7. import * as PDFJS from ''pdfjs-dist/legacy/build/pdf.mjs''
  8. import * as PdfWorker from ''pdfjs-dist/legacy/build/pdf.worker.mjs''
  9. import { nextTick, ref, Ref, watch } from ''vue''
  10. import { isEmpty, debounce } from ''lodash-es''
  11. const props: any = defineProps({
  12. pdf: {
  13. required: true
  14. }
  15. })
  16. let pdfDoc: any = null
  17. const pdfPages: Ref = ref(0)
  18. const pdfScale: Ref = ref(1.3)
  19. const loadFile = async (url: any) => {
  20. // 设定pdfjs的 workerSrc 参数
  21. PDFJS.GlobalWorkerOptions.workerSrc = PdfWorker
  22. const loadingTask = PDFJS.getDocument(url)
  23. loadingTask.promise.then(async (pdf: any) => {
  24. pdfDoc = pdf // 保存加载的pdf文件流
  25. pdfPages.value = pdfDoc.numPages // 获取pdf文件的总页数
  26. await nextTick(() => {
  27. renderPage(1) // 将pdf文件内容渲染到canvas
  28. })
  29. }).catch((error: any) => {
  30. //可以用自己组件库弹出提示框
  31. console.log(error)
  32. })
  33. }
  34. const renderPage = (num: any) => {
  35. pdfDoc.getPage(num).then((page: any) => {
  36. page.cleanup()
  37. const canvas: any = document.getElementById(`pdf-canvas-${num}`)
  38. if (canvas) {
  39. const ctx = canvas.getContext(''2d'')
  40. const dpr = window.devicePixelRatio || 1
  41. const bsr = ctx.webkitBackingStorePixelRatio ||
  42. ctx.mozBackingStorePixelRatio ||
  43. ctx.msBackingStorePixelRatio ||
  44. ctx.oBackingStorePixelRatio ||
  45. ctx.backingStorePixelRatio ||
  46. 1
  47. const ratio = dpr / bsr
  48. const viewport = page.getViewport({ scale: pdfScale.value })
  49. canvas.width = viewport.width * ratio
  50. canvas.height = viewport.height * ratio
  51. canvas.style.width = viewport.width + ''px''
  52. canvas.style.height = viewport.height + ''px''
  53. ctx.setTransform(ratio, 0, 0, ratio, 0, 0)
  54. const renderContext = {
  55. canvasContext: ctx,
  56. viewport: viewport
  57. }
  58. page.render(renderContext)
  59. if (num < pdfPages.value) {
  60. renderPage(num + 1)
  61. }
  62. }
  63. })
  64. }
  65. const debouncedLoadFile = debounce((pdf: any) => loadFile(pdf), 1000)
  66. watch(() => props.pdf, (newValue: any) => {
  67. !isEmpty(newValue) && debouncedLoadFile(newValue)
  68. }, {
  69. immediate: true
  70. })
  71. </script>
  72. <style scoped lang="less">
  73. .pdf-container {
  74. width: 100%;
  75. height: 100%;
  76. overflow: auto; /* 启用滚动条 */
  77. }
  78. canvas {
  79. width: 100%;
  80. max-height: 100vh; /* 设置最大高度为视口高度 */
  81. }
  82. </style>

 父组件:

  1. <!-- pdf展示 -->
  2. <div class="leftMain">
  3. <PdfView :pdf="jsPdf" style="width: 100%;height:100%;"></PdfView>
  4. </div>
  5. 。。。
  6. import jsPdf from ''../../../assets/pdf/pdf1.pdf''

如果需要使用点击跳页的话,用一个变量控制 页码,然后在canvas上换成变量,每次跳页就+-数字就好,位置可以自己定位到需要位置。

注意:

不同vite版本引用路径可能不同:

New Image

如果不知道在哪,可以点开node_modules找到pdfjs-dist对应去改一下就好

版本会引起报各种错,需要注意,实在不行复制错误搜索就好。。。

当前时间是可以使用的,刚实现过,后续如果不可以用了,可能是安装东西的版本迭代了。。重新安装的时候版本不同了

优化空间

不分页的话加载过大文件时速度很慢,可以懒加载 ,也可以分页

样式美化

 借鉴文章:import引入pdfjs-dist报错Top-level await is not available、No "GlobalWorkerOptions.workerSrc"等 - ziChin - 博客园 (cnblogs.com)