vue3+vite展示pdf

时间:2025-01-19 16:07:11

vue3+vite展示pdf

相较于vue2对pdf的兼容来说,vue3十分差,尤其是我们还用了vite,百度到的资料目前没有这方面的,大多只是查到 vue3对pdf的兼容,一些资料显示修改,但对于vite开发来说,根本无法修改
如果你只是展示pdf不做分页处理的话,那么你可以参考下面这个文档

https://www.52pojie.cn/thread-1391808-1-1.html

我们已经尝试过 ,他是可以做出来的,但是我们的项目要求必须分页,做的是一个教育项目,分页有利于记录学习进度,所以这个并不是很适合我们。
之后有参考了几个文档,其中

https://blog.****.net/houlai_houlai/article/details/86536316

这个有利于你了解你的版本号,2.0.943版本前后在写法上有区别,我们当时用的是大于这个版本的,这个只要注意一下就好了,不要因为写法引起差错。
参考的第二个文件是

https://www.cnblogs.com/kanglinen/p/10779185.html

这个文件大部分代码都是对的,但是引入方式不对,以及在渲染的时候,不知道为啥出不来,按照文件所说的引入方式,

import PDFJS from "pdfjs-dist";
import pdfjsLib from "pdfjs-dist";

你打印的永远是undefined,这时候你会质疑,觉得pdf底层代码是不是根本没有export出来,当时我也是这么想的,说实话,根本看不懂,所以无奈之举,只能各种尝试引入方式,首先require也不行,后来发现用

import * as PDFJS from "pdfjs-dist";
import * as pdfjsLib from "pdfjs-dist";

这种引入是可以的,这个灵感来自于,echart,再用echart的时候也发现了,像这种引入方式

import echarts from 'echarts';

也不行,具体啥原因,怀疑是vue3,但是 技术不够 ,也行不明白。
最后又参考了我同事昨天看的资料,跟上面的那个文件结合了一下,就好了
以下是源代码

<template>
  <div ref="pdfbox">
    {{pages}}
    <canvas :id="'the-canvas'+num"></canvas>
    <div @click='previous'>上一页</div>
    <div>{{num}}/{{pages}}</div>
    <div @click="next">下一页</div>
  </div>
</template>

<script>
import * as PDFJS from "pdfjs-dist";
import * as pdfjsLib from "pdfjs-dist";
// const Base64 = require('js-base64').Base64
export default {
  name: "ContractPreview",
  data() {
    return {
      title: "查看协议",
      pdfDoc: null,
      pages: 0,
      num: 1
    };
  },
  methods: {
    // 初始化pdfjs
    initThePDFJSLIB: function () {
      pdfjsLib.GlobalWorkerOptions.workerSrc = "../statics/pdf/build/";
    },
    /* pdf渲染 */
    _renderPage(num) {
      console.log(num)
      this.pdfDoc.getPage(num).then(page => {
        let canvas = document.getElementById("the-canvas" + num);
        let ctx = canvas.getContext("2d");
        const viewport = page.getViewport({ scale: 2 });
        var CSS_UNITS = 96.0 / 72.0;
        canvas.height = Math.floor(viewport.height * CSS_UNITS);
        canvas.width = Math.floor(viewport.width * CSS_UNITS);
        // 画布的dom大小, 设置移动端,宽度设置铺满整个屏幕
        const clientWidth = canvas.width;
        canvas.style.width = clientWidth + "px";
        // 根据pdf每页的宽高比例设置canvas的高度
        canvas.style.height =
          clientWidth * (canvas.height / canvas.width) + "px";
        page.render({
          transform: [CSS_UNITS, 0, 0, CSS_UNITS, 0, 0],
          canvasContext: ctx,
          viewport,
        });
      });
    },
    /* 获取pdf相关信息 */
    _loadFile(url) {
      const loadingTask = pdfjsLib.getDocument(url);
      loadingTask.promise.then((pdf) => {
        this.pdfDoc = pdf;
        this.pages = this.pdfDoc.numPages;
        this.$nextTick(() => {
          this._renderPage(1);
        });
      });
    },
    /* 下一页 */
    next() {
      this.num++
      this._renderPage(this.num)
    },
    /* 上一页 */
    previous() {
      this.num--
      this._renderPage(this.num)
    }
  },
  mounted() {
    this.initThePDFJSLIB();
    document.title = this.title;
    let url = '../statics/';
    this._loadFile(url);
  }
};
</script>

<style scoped>
canvas {
  display: block;
  border-bottom: 1px solid black;
}
</style>

因为我们的分页是点击下一页,上一页的,所以又做了修改,目前这个适合我们的,你们要是想直接展示所有的就参考,第一个文档,要是想分页,但是还是展示所有的页面,那就参考第三个文档和我们这个结合一下。

最后,走的时候留下个赞啊
在这里插入图片描述