Vue借助turn.js实现翻书效果预览pdf文件

1. 安装 turn.js

需要jQuery

turn.js官网

2. 安装 pdf.js

npm install vue-pdf --save-dev

3. 主体代码

<template>
  <div id="flipbook" ref="flipbook" v-loading="pdfLoading" v-show="rendered">
    <div v-for="item in pageNum" :key="item">
      <div class="gradient"></div>
      <canvas :id="`pdf-canvas-${item}`" class="pdf-page" />
    </div>
  </div>
</template>

<script>
import $ from "jquery";
import turn from "../../assets/js/turn.min.js";

import * as pdfjs from "pdfjs-dist";
import * as pdfjsWorker from "pdfjs-dist/build/pdf.worker.entry";

pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;

// console.log(pdfjs);
export default {
  name: "PdfTurnViewer",
  props: {
    pdfUrl: {
      type: String,
      default: "",
    },
  },
  data() {
    return {
      pdfLoading: false,
      rendered: false,
      pageNum: 0,
      pdfCtx: null,
      pageSize: {
        width: 0,
        height: 0,
      },
    };
  },
  mounted() {
    this.getPdf(this.pdfUrl);
    // this.startTurn();
  },
  methods: {
    getPdf(url) {
      this.pdfLoading = true;
      const loadingTask = pdfjs.getDocument(url);
      // console.log(loadingTask);
      loadingTask.promise
        .then((pdf) => {
          this.pdfCtx = pdf;
          this.pageNum = pdf.numPages;
          this.$nextTick(() => {
            this.renderPdf();
          });
        })
        .catch((err) => {
          this.pdfLoading = false;
          console.error("pdf加载失败", err);
        });
    },
    renderPdf(num = 1) {
      this.pdfCtx.getPage(num).then((page) => {
        const canvas = document.getElementById(`pdf-canvas-${num}`);
        const ctx = canvas.getContext("2d");
        const viewport = page.getViewport({ scale: 1 });

        this.pageSize = {
          width: viewport.width,
          height: viewport.height,
        };
        canvas.width = viewport.width;
        canvas.height = viewport.height;

        const clientWidth = 500;
        canvas.style.width = clientWidth + "px";
        // // 根据pdf每页的宽高比例设置canvas的高度
        // canvas.style.height =
        //   clientWidth * (viewport.height / viewport.width) + "px";

        page.render({
          canvasContext: ctx,
          viewport,
        });

        if (num < this.pageNum) {
          this.renderPdf(num + 1);
        } else {
          this.pdfLoading = false;
          this.rendered = true;
          console.log("render finished!");
          this.startTurn();
          // loading.clear();
        }
      });
    },
    startTurn() {
      let self = this;
      $("#flipbook").turn("center");
      $("#flipbook").turn("page");
      // this.$nextTick(() => {
      $("#flipbook")
        .turn({
          display: "double", //single double
          elevation: 50,
          gradients: true,
          duration: 1000,
          autoCenter: true,
          acceleration: true,
          page: 2,
          width: 1000,
          height: (self.pageSize.height * 1000) / self.pageSize.width / 2,
          when: {
            turning: (event, page, pageObj) => {
              // 禁止第1页时点击翻页
              page === 1 && event.preventDefault();
              // console.log(self.pageSize);
              // console.log("翻页中", page); //246偶数
              // if (page === this.numPages - 3) {
              //   console.log("加载下一页");
              //   this.numPages++;
              // }
            },
            // turned: (event, page, pageObj) => {
            //   //当前页
            //   console.log("当前页: ", page);
            //   console.log("当前页数组: ", pageObj);
            //   //总页数
            //   // console.log("共有" + $("#flipbook").turn("pages") + " 页");
            // },
          },
        })
        .bind("start", function (event, pageObject, corner) {
          // console.log("hover位置方向", corner);
          if (pageObject.page === 2) {
            // 禁止第1页时手动拖拽翻页
            event.preventDefault();
          }
        });
      // .bind("turning", (event, page, view) => {
      //   alert("turning the page to" + page);
      // });
      // .bind("last", function (event, pageObject, corner) {
      //   console.log("最后一页");
      // });
      // });
      // 销毁
      // $("#flipbook").turn("destroy").remove();
    },
  },
};
</script>

<style scoped>
.container {
  width: 100%;
  height: 100%;
  text-align: center;
}
#flipbook {
  height: 800px;
}
#flipbook .even .gradient {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: -webkit-gradient(
    linear,
    left top,
    right top,
    color-stop(0.95, rgba(0, 0, 0, 0)),
    color-stop(1, rgba(0, 0, 0, 0.2))
  );
}
</style>
posted @ 2022-06-09 21:21  Li_pk  阅读(2026)  评论(4编辑  收藏  举报