vue实现pdf预览加分页轮播

参考 https://github.com/FranckFreiburger/vue-pdf

1、 安装依赖

npm install pdfjs-dist -save

2、项目使用

创建pdf 预览的组件 pdf.vue
代码如下:

<template>
  <div>
    <el-carousel indicator-position="none" arrow="always" :autoplay="false" trigger="click">
      <el-carousel-item
        v-for="page in docPages"
        :key="page"
      >
        <div class="page-container" ref="container">
          <canvas
            v-if="renderList.includes(page)"
            :style="{
        height: `${pageHeight}px`
      }"
          ></canvas>
          <div class="notice" v-if="show">{{ notice }}</div>
        </div>
      </el-carousel-item>
    </el-carousel>
  </div>
</template>

<script>
import pdfJS from "pdfjs-dist";
pdfJS.GlobalWorkerOptions.workerSrc =
  "../../../node_modules/pdfjs-dist/build/pdf.worker.js";
export default {
  props: {
    url: {
      type: String,
      required: true
    },
    renderPages: {
      type: Number,
      default: 5
    },
    customScroll: {
      type: Boolean,
      default: false
    },
    offsetHeight: {
      type: Number,
      default: 0
    }
  },
  data() {
    return {
      doc: null,
      docPages: 0,
      currentPage: 0,
      pageHeight: 0,
      renderList: [],
      show: false,
      notice: "",
      timer: 0
    };
  },
  watch: {
    url: {
      immediate: true,
      handler() {
        this.getPDFFile();
      }
    }
  },
  created() {
    if (!this.customScroll) {
      document.addEventListener("scroll", this.scroll);
    }
  },
  beforeDestroy() {
    document.removeEventListener("scroll", this.scroll);
  },
  methods: {
    xiayiye() {
      this.renderPage(3);
    },
    shangyiye() {
      this.currentPage--;
    },
    getPDFFile() {
      if (!this.url) return;
      this.currentPage = 0;
      let pdfTask = pdfJS.getDocument(this.url);
      pdfTask.promise.then(pdf => {
        this.doc = pdf;
        this.docPages = pdf.numPages;
        this.$nextTick(() => {
          this.docPages && this.scrollToPage(1);
        });
      });
    },
    scrollToPage(pageNo) {
      if (this.currentPage === pageNo) return;
      this.currentPage = pageNo;
      let list = [];
      for (
        let page = pageNo - this.docPages;
        page <= pageNo + this.docPages;
        page++
      ) {
        list.push(page);
      }
      list = list.filter(page => page <= this.docPages && page >= 1);
      this.$nextTick(() => {
        this.renderList = list;
        this.renderList.forEach(page => {
          this.renderPage(page);
        });
      });
    },
    // 渲染page
    renderPage(pageNo) {
      this.doc.getPage(pageNo).then(page => {
        let container = this.$refs.container[pageNo - 1];
        if (!container) return;
        let canvas = container.querySelector("canvas");
        if (!canvas || canvas.__rendered) return;
        let ctx = canvas.getContext("2d");
        let dpr = window.devicePixelRatio || 1;
        let bsr =
          ctx.webkitBackingStorePixelRatio ||
          ctx.mozBackingStorePixelRatio ||
          ctx.msBackingStorePixelRatio ||
          ctx.oBackingStorePixelRatio ||
          ctx.backingStorePixelRatio ||
          1;
        let ratio = dpr / bsr;
        let rect = container.getBoundingClientRect();
        let viewport = page.getViewport({ scale: 1 });
        let width = rect.width;
        let height = (width / viewport.width) * viewport.height;
        canvas.style.width = `${width}px`;
        canvas.style.height = `${height}px`;
        this.pageHeight = height;
        canvas.height = height * ratio;
        canvas.width = width * ratio;
        ctx.setTransform(ratio, 0, 0, ratio, 0, 0);
        page.render({
          canvasContext: ctx,
          viewport: page.getViewport({ scale: width / viewport.width })
        });
        canvas.__rendered = true;
      });
    },
    scroll() {
      this.checkRender(document.documentElement);
    },
    checkRender(el) {
      if (!this.pageHeight) return;
      let scrollTop = el.scrollTop;
      if (el === document.documentElement) {
        scrollTop =
          el.scrollTop || window.pageYOffset || document.body.scrollTop;
      }
      let page = Math.floor((scrollTop - this.offsetHeight) / this.pageHeight);
      page = Math.max(page, 1);
      page = Math.min(page, this.docPages);
      this.scrollToPage(page);
    }
  }
};
</script>

创建pdfPreview.vue
引入pdf 预览的组件 pdf.vue

<template>
  <div>
    <pdf-preview :url="url"></pdf-preview>
  </div>
</template>

<script>
import pdfPreview from "./pdf.vue";
export default {
  name: "pdf",
  components: {
    pdfPreview
  },
  data() {
    return {
      url: "../../../../static/java.pdf"
    };
  }
};
</script>
<style>
</style>
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值