vue中使用pdfjs-dist + turnjs实现页面的翻书浏览功能

Vue
472
0
0
2023-06-09
目录
  • 首先 安装 psfjs-dist
  • vue中安装jquery的方法
  • 下载trunjs

pdfjs-dist 的工作原理:把获取到的 pbf 的文件的数据流, 利用 canvas转换成图片

turnjs 把多个元素做成翻书的特效

我接手了一个展示大屏的项目, 其中有一个地方,就是要以翻书的形式来预览 pdf文件

如图

请添加图片描述

首先 安装 psfjs-dist

npm install --save pdfjs-dist

turnjs 是jquery的项目, 所以, 我们要在vuejs中安装 jquery

vue中安装jquery的方法

npm install jquery --save

然后在 vue.config.js中配置

module.exports = {
  chainWebpack: config => {
    config.plugin('provide').use(webpack.ProvidePlugin, [{
      $: 'jquery',
      jquery: 'jquery',
      jQuery: 'jquery',
      'window.jQuery': 'jquery'
    }])
  }

下载trunjs

http://www.turnjs.com/ 官网下载

我写这个笔记的时候, 官网好像下载出错了,我找到了另一种下载的方法

把官网的示例随便打开了个, 找到 上图中的地址

这样也可以得到我们想要的 trunjs库

上面是安装, 下面我们开始使用

       <div class="body-content" style="height:px;">
                      <v-touch @swipeleft="changeindexleft()" @swiperight="changeindexright(1)">
                      <div id="magazine" style="height:850px;width:1200px;margin-left:0 !important;">
                        <!-- 这里的 magazine  就是翻页组件的容器 -->
                      </div>
                      </v-touch>
                          <!-- 这里的 docview 是用来存放 pdf转成图片时,所用到的 canvas 标签的-->
                      <div style="margin: auto; text-align: center; display: none">
                        <div id="docView" ref="docView1"></div>
                      </div>
                    </div>

代码部份

引入 jquery 和 turnjs

import $ from "jquery";
import * as PDFJS from "pdfjs-dist";
import turn from "../utils/lib/turn.js"
//初始化pdf插件
    /*
     ** @param fileUrl pdf有效的查看地址
     **				(、线上地址(如:http://www.xxx.com)
     **、本地public地址(例如:/static/view.pdf))
     ** @param  pdfPicturePath pdf转化的图片地址-用于放大查看所有pdf图片
     */
    readPdf(fileUrl,index) {
    	//这个index 是我代码中要用的, 如果单独使用的话, 可以不要 index 这个参数
      let self = this;
        let loadingTask = PDFJS.getDocument(fileUrl);  //读取pdf文件
        console.log(loadingTask, '-----------loadingTask');
        loadingTask.promise
            .then(function (pdf) {
              if (pdf) {
                // pdf 总页数
                const pageNum = pdf.numPages;
                for (let i =; i <= pageNum; i++) {
                  // 生成每页 pdf 的 canvas
                  const canvas = document.createElement('canvas');
                  canvas.id = 'page'+index+'Num' + i;
                  canvas.className = 'h'+index;
                  // 将 canvas 添加到 dom 中,docView(存放canvas的div)
                  let docViewX = "docView"+index;
                  console.log(docViewX);
                  self.$refs[docViewX].append(canvas);
                  //getContext() 方法返回一个用于在画布上绘图的环境。
                  const context = canvas.getContext('d');
                  self.openPage(pdf, i, context);
                }
                setTimeout(() => {
                  self.exportImg(self,index);
                },);
              }
            })
            .catch(function (reason) {
              console.error('Error: ' + reason);
            });
   
    },



//pdf转成canvas
    /*
     ** @param loading pdf生成图片时的加载状态
     ** @param scale 控制 canvas显示的大小
     */
    openPage(pdfFile, pageNumber, context) {
      let that = this;
      pdfFile.getPage(pageNumber).then(function (page) {
        // reference canvas via context
        let viewport = page.getViewport({scale:});
        let scale =( / viewport.height).toFixed(2)  //这里根把自已的项目需求,宽高进行调整
        let viewport = page.getViewport({scale:scale});

        let canvas = context.canvas;
        canvas.width = viewport.width;
        canvas.height = viewport.height;
        canvas.style.width = '%';
        canvas.style.height = '%';

        let renderContext = {
          canvasContext: context,
          viewport: viewport
        };
        page.render(renderContext);
        that.loading = false;
      });
      return;
    },



//canvas转成图片(可根据具体情况,进行图片转化显示)这里我把所有图片的base存放在数组里面,方便放大查看,也可以直接把生成图片标签进行图片展示
    // 转图片
    exportImg(self,index) {
      //let canvaslist= document.querySelectorAll('canvas');
      let canvaslist = document.getElementsByClassName("h"+index);
      let pdfPicturePathX = "pdfPicturePath"+index;
      this[pdfPicturePathX] = [];
      //这里把所有的图片地址放入到 pdfPicturePath 数组中去
      for (let i =; i < canvaslist.length; i++) {
        // let canvas = document.getElementById("pageNum" + (i +));
        // // 将 canvas 转成 base 格式的图片
        // let baseImgSrc = (canvas as any).toDataURL("image/png")
        // const img = document.createElement("img")
        // img.setAttribute('class', 'pdf-img');
        // img.src = baseImgSrc
        // img.style.width = '%';
        // // 将图片挂载到 dom 中
        // (self.$refs as any).docView.append(img);
        let canvasNode = document.getElementById('page'+index+'Num' + (i +));
        // 将 canvas 转成 base 格式的图片
        if(canvasNode){
          this[pdfPicturePathX].push({page: i +, pic: canvasNode.toDataURL('image/png'), name: i + 1})
        }else {
          continue;
        }
        //console.log('--------------aaa-------------', this.pdfPicturePath);
      }
	//到上面就是把pdf文件转成 base格式的图片, 之后把它们存在 pdfPicturePath1的数组中

      this.$nextTick(()=>{
        if(index ==){
          if($("#magazine").children().length > 0){
            $("#magazine").turn("destroy");
            $("#magazine").children().remove();
          }
          let magazine = $("#magazine1");
          this[pdfPicturePathX].forEach(i=>{
            magazine.append("<img src='"+i.pic+"'/>")
          });

          //setTimeout(()=>{

            $("#magazine").turn({
              autoCenter: true,
              elevation:,
              acceleration: true,
              //direction:"rtl",
              // when: {
              //   turned: function() {
              //     //当前页
              //     // console.log("Current view: ", $(this).turn("view"));
              //     // //总页数
              //     // console.log(
              //     //     "#magazine has " + $("#magazine").turn("pages") + " pages"
              //     // );
              //     //$("#magazine").turn("hasPage",);
              //     //$("#magazine").turn("pages",);
              //   }
              // }
            })
          $("#magazine").turn("center");
          $("#magazine").turn("page");

          //console.log($("#magazine").turn("pages"));
            $("#magazine").bind("start",function(e,p,c){
              if(c == "tl"||c == 'tr'){
                e.preventDefault();
              }
            })
          //},
        }
    },


下面是我项目的一个完现代码

<template>
  <div id="index" ref="appRef">

    <div class="bg">
      <dv-loading v-show="loading">Loading...</dv-loading>
      <div v-show="!loading" class="host-body">
        <!--        第一行-->

        <div class="row">
          <div class="title-wrapper">
            <img src="../assets/pic_rczs_title.png">
            <fullscreen ref="fullscreen" style="float:right"></fullscreen>
          </div>
        </div>
        <!-- 第二行 -->
        <div class="row">
          <div class="item_">
            <div class="picwrapper" v-show="showfengmian">
              <div class="initem" v-if="categoryslist[]" @click="fengmianclick(1,0)">
                <img :src="categoryslist[].more.thumbnail"/>
                <div class="intitle">{{categoryslist[].name}}</div>
              </div>
              <div class="initem"  v-if="categoryslist[]" @click="fengmianclick(1,1)">
                <img :src="categoryslist[].more.thumbnail"/>
                <div class="intitle">{{categoryslist[].name}}</div>
              </div>
            </div>

            <div class="detailwrapper" v-show="!showfengmian">
              <div class="dtop">
                <img src="../assets/pic_qyzc_shrcxzsy.png"/>
              </div>
              <div class="btmwrapper">
                <div class="left">
                  <img src="../assets/icon_fanhui.png" @click="backtoshow()"/>
                </div>
                <div class="right">
                  <div class="content" v-show="!showpdf">
                    <div class="listdetailwrapper">
                      <div class="listtop">
                        <multiselect v-model="value"
                                     placeholder="请选择"
                                     open-direction="bottom"
                                     :show-labels="false"
                                     trackBy="id"
                                     label="name"
                                     @select="chooseSelect"
                                     :options="selectoptions">
                        </multiselect>
                      </div>
                      <div class="listwrapper">
                        <div @click="chooselist(,index,item)" class="listitem" :class="selectItemIndex1 == index?'coloractive':''" v-for="(item,index) in selectList1" :key="item.id">{{item.name}}<span style="float: right" v-if="selectItemIndex1 == index"></span></div>
                      </div>
                    </div>
                    <div class="detail" :style="{height:ispdf?'':'100%'}">
                      <div v-if="!ispdf" class="markdown-body editor" v-html="articleDetail1.post_content"></div>
                      <div class="img-wrapper" v-if="ispdf" @click="pdfshowClick(1,articleDetail1.more.files)">
                        <img class="img" src="../assets/pic_mrfm_wj@2x.png"/>
                      </div>
                    </div>
                  </div>
                  <div class="pdf-wrapper"  v-show="showpdf">
                    <div class="body-content" style="height:px;">
                      <v-touch @swipeleft="changeindexleft()" @swiperight="changeindexright(1)">
                      <div id="magazine" style="height:850px;width:1200px;margin-left:0 !important;">

<!--                        <div v-for="(item, index) in pdfPicturePath" :key="`test_${index}`">-->
<!--                          <div>-->
<!--                            <v-touch @swipeleft="changeindexleft()" @swiperight="changeindexright(1)">-->
<!--                            <img :src="item.pic" class="pdf_pic" />-->
<!--                            </v-touch>-->
<!--                          </div>-->
<!--                        </div>-->
                      </div>
                      </v-touch>
                      <div style="margin: auto; text-align: center; display: none">
                        <div id="docView" ref="docView1"></div>
                      </div>
                    </div>

                  </div>
                </div>
              </div>

            </div>
          </div>

          <div class="item_">
            <div class="picwrapper" v-show="showfengmian">
              <div class="initem" v-if="categoryslist[]" @click="fengmianclick(2,2)">
                <img :src="categoryslist[].more.thumbnail"/>
                <div class="intitle">{{categoryslist[].name}}</div>
              </div>
              <div class="initem"  v-if="categoryslist[]" @click="fengmianclick(2,3)">
                <img :src="categoryslist[].more.thumbnail"/>
                <div class="intitle">{{categoryslist[].name}}</div>
              </div>
            </div>

            <div class="detailwrapper" v-show="!showfengmian">
              <div class="dtop">
                <img src="../assets/pic_qyzc_shrcxzsy.png"/>
              </div>
              <div class="btmwrapper">
                <div class="left">
                  <img src="../assets/icon_fanhui.png" @click="backtoshow()"/>
                </div>
                <div class="right">
                  <div class="content" v-show="!showpdf">
                    <div class="listdetailwrapper">
                      <div class="listtop">
                        <multiselect v-model="value"
                                     placeholder="请选择"
                                     open-direction="bottom"
                                     :show-labels="false"
                                     trackBy="id"
                                     label="name"
                                     @select="chooseSelect"
                                     :options="selectoptions">
                        </multiselect>
                      </div>
                      <div class="listwrapper">
                        <div @click="chooselist(,index,item)" class="listitem" :class="selectItemIndex2 == index?'coloractive':''" v-for="(item,index) in selectList2" :key="item.id">{{item.name}}<span style="float: right" v-if="selectItemIndex2 == index"></span></div>
                      </div>
                    </div>
                    <div class="detail" :style="{height:ispdf?'':'100%'}">
                      <div v-if="!ispdf" class="markdown-body editor" v-html="articleDetail2.post_content"></div>
                      <div class="img-wrapper" v-if="ispdf" @click="pdfshowClick(2,articleDetail2.more.files)">
                        <img class="img" src="../assets/pic_mrfm_wj@2x.png"/>
                      </div>
                    </div>
                  </div>
                  <div class="pdf-wrapper"  v-show="showpdf">
                    <div class="body-content" style="height:px;">
                      <v-touch @swipeleft="changeindexleft()" @swiperight="changeindexright(2)">
                      <div id="magazine" style="height:850px;width:1200px;margin-left:0 !important;">

<!--                        <div v-for="(item, index) in pdfPicturePath" :key="`test_${index}`">-->
<!--                          <div>-->
<!--                            <v-touch @swipeleft="changeindexleft()" @swiperight="changeindexright(2)">-->
<!--                              <img :src="item.pic" class="pdf_pic" />-->
<!--                            </v-touch>-->
<!--                          </div>-->
<!--                        </div>-->
                      </div>
                      </v-touch>
                      <div style="margin: auto; text-align: center; display: none">
                        <div id="docView" ref="docView2"></div>
                      </div>
                    </div>

                  </div>
                </div>
              </div>

            </div>
          </div>

          <div class="item_">
            <div class="picwrapper" v-show="showfengmian">
              <div class="initem" v-if="categoryslist[]" @click="fengmianclick(3,4)">
                <img :src="categoryslist[].more.thumbnail"/>
                <div class="intitle">{{categoryslist[].name}}</div>
              </div>
              <div class="initem"  v-if="categoryslist[]" @click="fengmianclick(3,5)">
                <img :src="categoryslist[].more.thumbnail"/>
                <div class="intitle">{{categoryslist[].name}}</div>
              </div>
            </div>

            <div class="detailwrapper" v-show="!showfengmian">
              <div class="dtop">
                <img src="../assets/pic_qyzc_shrcxzsy.png"/>
              </div>
              <div class="btmwrapper">
                <div class="left">
                  <img src="../assets/icon_fanhui.png" @click="backtoshow()"/>
                </div>
                <div class="right">
                  <div class="content" v-show="!showpdf">
                    <div class="listdetailwrapper">
                      <div class="listtop">
                        <multiselect v-model="value"
                                     placeholder="请选择"
                                     open-direction="bottom"
                                     :show-labels="false"
                                     trackBy="id"
                                     label="name"
                                     @select="chooseSelect"
                                     :options="selectoptions">
                        </multiselect>
                      </div>
                      <div class="listwrapper">
                        <div @click="chooselist(,index,item)" class="listitem" :class="selectItemIndex3 == index?'coloractive':''" v-for="(item,index) in selectList3" :key="item.id">{{item.name}}<span style="float: right" v-if="selectItemIndex3 == index"></span></div>
                      </div>
                    </div>
                    <div class="detail" :style="{height:ispdf?'':'100%'}">
                      <div v-if="!ispdf" class="markdown-body editor" v-html="articleDetail3.post_content"></div>
                      <div class="img-wrapper" v-if="ispdf" @click="pdfshowClick(3,articleDetail3.more.files)">
                        <img class="img" src="../assets/pic_mrfm_wj@2x.png"/>
                      </div>
                    </div>
                  </div>
                  <div class="pdf-wrapper"  v-show="showpdf">
                    <div class="body-content" style="height:px;">
                      <v-touch @swipeleft="changeindexleft()" @swiperight="changeindexright(3)">
                      <div id="magazine" style="height:850px;width:1200px;margin-left:0 !important;">
<!--                        <div v-for="(item, index) in pdfPicturePath" :key="`test_${index}`">-->
<!--                          <div>-->
<!--                            <v-touch @swipeleft="changeindexleft()" @swiperight="changeindexright(3)">-->
<!--                              <img :src="item.pic" class="pdf_pic" />-->
<!--                            </v-touch>-->
<!--                          </div>-->
<!--                        </div>-->
                      </div>
                      </v-touch>
                      <div style="margin: auto; text-align: center; display: none">
                        <div id="docView" ref="docView3"></div>
                      </div>
                    </div>

                  </div>
                </div>
              </div>

            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import drawMixin from "../utils/drawMixin";
import "github-markdown-css/github-markdown.css"
import fullscreen from "@/views/fullscreen";
import Multiselect from "vue-multiselect";
import $ from "jquery";
import * as PDFJS from "pdfjs-dist";
import turn from "../utils/lib/turn.min.js"
import M from "../model/m";

export default {
  mixins: [ drawMixin ],
  data() {
    return {

      categoryslist:[],   //首页的分类列表, 一共有六个分类

      //下拉选择框 三个
      selectoptions:[
      ],
      selectoptions:[],
      selectoptions:[],
      //下拉选择框的值 三个
      value:{},
      value:{},
      value:{},
      //下拉选择后的列表 三个
      selectList:[],
      //列表中选中的标记, 主要是为了显示 条目中的小箭头
      selectItemIndex:-1,
      selectList:[],
      selectItemIndex:-2,
      selectList:[],
      selectItemIndex:-3,

      //标记pdf记号
      ispdf:false,
      ispdf:false,
      ispdf:false,


      //showpdf div的标记
      showpdf:false,
      showpdf:false,
      showpdf:false,


      showfengmian:true,
      showfengmian:true,
      showfengmian:true,

      articleDetail:{},
      articleDetail:{},
      articleDetail:{},



      pdfPicturePath: [], // pdf转化的图片地址
      pdfPicturePath: [], // pdf转化的图片地址
      pdfPicturePath: [], // pdf转化的图片地址

      loading:true,
    }
  },
  components: {
    fullscreen,
    Multiselect
  },


  computed:{

  },


  mounted() {

    this.initData();


    //this.timeFn()

    //this.readPdf("bbb.pdf")
    this.cancelLoading();
    this.$refs.fullscreen.toggleFullScreen();



  },


  beforeDestroy () {

  },
  methods: {

    chooseSelect(selectoption){
      this.getSelectList(selectoption,);
    },

    chooseSelect(selectoption){
      this.getSelectList(selectoption,);
    },

    chooseSelect(selectoption){
      this.getSelectList(selectoption,);
    },

    initData(){
      //得到首页的图片列表
      M.getCategorys().then(res=>{
        this.categoryslist = res.data.categories;
      })
    },



    //封面被点击
    fengmianclick(index,categoryslistindex){
      console.log(index,categoryslistindex);
      //index 表示是哪一列中的(本屏一共有三列)
      //categoryslistindex  被点击的在 categoryslist中的index
      let showfengmianX = "showfengmian"+index;
      this[showfengmianX] = false;
      let thecategory = this.categoryslist[categoryslistindex];
      M.getCategorys(thecategory.id).then(res=>{
        let selectoptions = res.data.categories;
        let selectoptionsX = "selectoptions"+index;
        this[selectoptionsX] = selectoptions;
        let valueX = "value"+index;
        this[valueX] = selectoptions[];
        //这里要显示默认的项的信息
        this.getSelectList(selectoptions[],index);
      })
    },


    getSelectList(value,index){
      //index表示第几列的
      let params = {
        category_id:value.id
      }
      M.getselectLists(params).then(res=>{
        console.log(res);
        let selectListX = "selectList"+index;
        let selectlist = res.data.map(i=>{
          i.name=i.post_title;
          if(i.tag ==){
            i.type = "txt"
          }else if(i.tag ==){
            i.type = "pdf";
          }
          return i;
        });
        this[selectListX] = selectlist;
        let selectItemIndexX = "selectItemIndex"+index;
        this[selectItemIndexX] =;
        let theselectItem = selectlist[];
        this.getArticleDetail(theselectItem,index);
      })
    },


    //通过文章id来显示文章的详情
    getArticleDetail(theselectItem,index){
      //index 第几列
      if(!theselectItem){
        let articleDetailX = "articleDetail"+index;
        this[articleDetailX] = [];
        return;
      }
      let ispdfX = "ispdf"+index;
      let article_id = theselectItem.id;
      this[ispdfX] = theselectItem.type == "pdf"?true:false
      M.getArticleDetail(article_id).then(res=>{
        let articleDetailX = "articleDetail"+index;
        this[articleDetailX] = res.data;
        if(theselectItem.type == "pdf"){
          this.readPdf(res.data.more.files[].url,index);
          //this.readPdf("bbb.pdf?"+Math.random(),index)
        }
      })
    },


    //回退
    backtoshow(index){
      //index 表示是哪一列中的(本屏一共有三列)
      let showpdfX = "showpdf"+index;
      //当 showpdfX == true是 一定是显示了pdf 的滑动页
      if(this[showpdfX]){
        this[showpdfX] = !this[showpdfX]
      }else{
        //如果是showpdfX 是 false ,那就应该是退回上一级的页面
        let showfengmianX = "showfengmian"+index;
        this[showfengmianX] = true;
      }
    },


    pdfshowClick(index,files){
      //index 表示是哪一列中的(本屏一共有三列)
      let showpdfX = "showpdf"+index;
      this[showpdfX] = true;
      //是在这里加载pdf ,还是在列表中点击的时候加载pdf 可以测试一下哪个要好一点
      //this.readPdf("bbb.pdf",index)
    },



    chooselist(index,listindex,item){
      //第一个index 表示是哪一列中的(本屏一共有三列)
      //listindex 表示点击的是哪一条数据
      let selectItemIndexX = "selectItemIndex"+index;
      this[selectItemIndexX] = listindex;
      let selectListX = "selectList"+index;
      //从selectListX中的数组中得到这条信息的具体内容,并标记是否是一个pdf文件
      //看后台的设计,这里可能是要请求接口的
      let ispdfX = "ispdf"+index;
      this[ispdfX] = this[selectListX][listindex].type == "pdf"?true:false
      this.getArticleDetail(item,index)
    },



    //书翻页
    changeindexleft(index){
      this.$nextTick(()=>{
        if(index ==){
          $("#magazine").turn("next")
        }else if(index ==){
          $("#magazine").turn("next")
        }else if(index ==){
          $("#magazine").turn("next")
        }
      })


    },
    changeindexright(index){
      this.$nextTick(()=>{
        if(index ==){
          $("#magazine").turn("previous")
        }else if(index ==){
          $("#magazine").turn("previous")
        }else if(index ==){
          $("#magazine").turn("previous")
        }
      })

    },

//初始化pdf插件
    /*
     ** @param fileUrl pdf有效的查看地址
     **				(、线上地址(如:http://www.xxx.com)
     **、本地public地址(例如:/static/view.pdf))
     ** @param  pdfPicturePath pdf转化的图片地址-用于放大查看所有pdf图片
     */
    readPdf(fileUrl,index) {
      let self = this;
      if(index ==){
        let loadingTask = PDFJS.getDocument(fileUrl);  //读取pdf文件
        console.log(loadingTask, '-----------loadingTask');
        loadingTask.promise
            .then(function (pdf) {
              if (pdf) {
                // pdf 总页数
                const pageNum = pdf.numPages;
                for (let i =; i <= pageNum; i++) {
                  // 生成每页 pdf 的 canvas
                  const canvas = document.createElement('canvas');
                  canvas.id = 'page'+index+'Num' + i;
                  canvas.className = 'h'+index;
                  // 将 canvas 添加到 dom 中,docView(存放canvas的div)
                  let docViewX = "docView"+index;
                  console.log(docViewX);
                  self.$refs[docViewX].append(canvas);
                  //getContext() 方法返回一个用于在画布上绘图的环境。
                  const context = canvas.getContext('d');
                  self.openPage(pdf, i, context);
                }
                setTimeout(() => {
                  self.exportImg(self,index);
                },);
              }
            })
            .catch(function (reason) {
              console.error('Error: ' + reason);
            });
      }
      if(index ==){
        let loadingTask = PDFJS.getDocument(fileUrl);  //读取pdf文件
        console.log(loadingTask, '-----------loadingTask');
        loadingTask.promise
            .then(function (pdf) {
              if (pdf) {
                // pdf 总页数
                const pageNum = pdf.numPages;
                for (let i =; i <= pageNum; i++) {
                  // 生成每页 pdf 的 canvas
                  const canvas = document.createElement('canvas');
                  canvas.id = 'page'+index+'Num' + i;
                  canvas.className = 'h'+index;
                  // 将 canvas 添加到 dom 中,docView(存放canvas的div)
                  let docViewX = "docView"+index;
                  console.log(docViewX);
                  self.$refs[docViewX].append(canvas);
                  //getContext() 方法返回一个用于在画布上绘图的环境。
                  const context = canvas.getContext('d');
                  self.openPage(pdf, i, context);
                }
                setTimeout(() => {
                  self.exportImg(self,index);
                },);
              }
            })
            .catch(function (reason) {
              console.error('Error: ' + reason);
            });
      }
      if(index ==){
        let loadingTask = PDFJS.getDocument(fileUrl);  //读取pdf文件
        console.log(loadingTask, '-----------loadingTask');
        loadingTask.promise
            .then(function (pdf) {
              if (pdf) {
                // pdf 总页数
                const pageNum = pdf.numPages;
                for (let i =; i <= pageNum; i++) {
                  // 生成每页 pdf 的 canvas
                  const canvas = document.createElement('canvas');
                  canvas.id = 'page'+index+'Num' + i;
                  canvas.className = 'h'+index;
                  // 将 canvas 添加到 dom 中,docView(存放canvas的div)
                  let docViewX = "docView"+index;
                  console.log(docViewX);
                  self.$refs[docViewX].append(canvas);
                  //getContext() 方法返回一个用于在画布上绘图的环境。
                  const context = canvas.getContext('d');
                  self.openPage(pdf, i, context);
                }
                setTimeout(() => {
                  self.exportImg(self,index);
                },);
              }
            })
            .catch(function (reason) {
              console.error('Error: ' + reason);
            });
      }


    },
    //pdf转成canvas
    /*
     ** @param loading pdf生成图片时的加载状态
     ** @param scale 控制 canvas显示的大小
     ** @param  pdfPicturePath pdf转化的图片地址-用于放大查看所有pdf图片
     */
    openPage(pdfFile, pageNumber, context) {
      let that = this;
      pdfFile.getPage(pageNumber).then(function (page) {
        // reference canvas via context
        let viewport = page.getViewport({scale:});
        let scale =( / viewport.height).toFixed(2)
        let viewport = page.getViewport({scale:scale});

        let canvas = context.canvas;
        canvas.width = viewport.width;
        canvas.height = viewport.height;
        canvas.style.width = '%';
        canvas.style.height = '%';

        let renderContext = {
          canvasContext: context,
          viewport: viewport
        };
        page.render(renderContext);
        that.loading = false;
      });
      return;
    },
    //canvas转成图片(可根据具体情况,进行图片转化显示)这里我把所有图片的base存放在数组里面,方便放大查看,也可以直接把生成图片标签进行图片展示
    // 转图片
    exportImg(self,index) {

      //let canvaslist= document.querySelectorAll('canvas');
      let canvaslist = document.getElementsByClassName("h"+index);
      let pdfPicturePathX = "pdfPicturePath"+index;
      this[pdfPicturePathX] = [];
      //这里把所有的图片地址放入到 pdfPicturePath 数组中去
      for (let i =; i < canvaslist.length; i++) {
        // let canvas = document.getElementById("pageNum" + (i +));
        // // 将 canvas 转成 base 格式的图片
        // let baseImgSrc = (canvas as any).toDataURL("image/png")
        // const img = document.createElement("img")
        // img.setAttribute('class', 'pdf-img');
        // img.src = baseImgSrc
        // img.style.width = '%';
        // // 将图片挂载到 dom 中
        // (self.$refs as any).docView.append(img);
        let canvasNode = document.getElementById('page'+index+'Num' + (i +));
        // 将 canvas 转成 base 格式的图片
        if(canvasNode){
          this[pdfPicturePathX].push({page: i +, pic: canvasNode.toDataURL('image/png'), name: i + 1})
        }else {
          continue;
        }
        //console.log('--------------aaa-------------', this.pdfPicturePath);
      }

      this.$nextTick(()=>{
        if(index ==){
          if($("#magazine").children().length > 0){
            $("#magazine").turn("destroy");
            $("#magazine").children().remove();
          }
          let magazine = $("#magazine1");
          this[pdfPicturePathX].forEach(i=>{
            magazine.append("<img src='"+i.pic+"'/>")
          });

          //setTimeout(()=>{

            $("#magazine").turn({
              autoCenter: true,
              elevation:,
              acceleration: true,
              //direction:"rtl",
              // when: {
              //   turned: function() {
              //     //当前页
              //     // console.log("Current view: ", $(this).turn("view"));
              //     // //总页数
              //     // console.log(
              //     //     "#magazine has " + $("#magazine").turn("pages") + " pages"
              //     // );
              //     //$("#magazine").turn("hasPage",);
              //     //$("#magazine").turn("pages",);
              //   }
              // }
            })
          $("#magazine").turn("center");
          $("#magazine").turn("page");

          //console.log($("#magazine").turn("pages"));
            $("#magazine").bind("start",function(e,p,c){
              if(c == "tl"||c == 'tr'){
                e.preventDefault();
              }
            })
          //},)



        }
        if(index ==){
          if($("#magazine").children().length > 0){
            $("#magazine").turn("destroy");
            $("#magazine").children().remove();
          }
          let magazine = $("#magazine2");
          this[pdfPicturePathX].forEach(i=>{
            magazine.append("<div><img src='"+i.pic+"'/></div>")
          });
          $("#magazine").turn("center");
          $("#magazine").turn("page");
          $("#magazine").turn({
            autoCenter: true,
            acceleration: true,
            //direction:"rtl",
            when: {
              turned: function() {
                //当前页
                // console.log("Current view: ", $(this).turn("view"));
                // //总页数
                // console.log(
                //     "#magazine has " + $("#magazine").turn("pages") + " pages"
                // );
                //$("#magazine").turn("hasPage",);
                //$("#magazine").turn("pages",);
              }
            }
          })
          $("#magazine").bind("start",function(e,p,c){
            if(c == "tl"||c == 'tr'){
              e.preventDefault();
            }
          })
        }

        if(index ==){
          if($("#magazine").children().length > 0){
            $("#magazine").turn("destroy");
            $("#magazine").children().remove();
          }
          let magazine = $("#magazine3");
          this[pdfPicturePathX].forEach(i=>{
            magazine.append("<div><img src='"+i.pic+"'/></div>")
          });
          $("#magazine").turn("center");
          $("#magazine").turn("page");
          $("#magazine").turn({
            autoCenter: true,
            acceleration: true,
            //direction:"ltr",
            when: {
              turned: function() {
                //当前页
                // console.log("Current view: ", $(this).turn("view"));
                // //总页数
                // console.log(
                //     "#magazine has " + $("#magazine").turn("pages") + " pages"
                // );
                //$("#magazine").turn("hasPage",);
                //$("#magazine").turn("pages",);
              }
            }
          })
          $("#magazine").bind("start",function(e,p,c){
            if(c == "tl"||c == 'tr'){
              e.preventDefault();
            }
          })
        }
      })
    },

    cancelLoading() {
      setTimeout(() => {
        this.loading = false
      },)
    }
  }
}
</script>

<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>

<style lang="scss" scoped>
@import '../assets/scss/index.scss';

.row{
  margin-top:px;
  .title-wrapper{
    position:relative;
    padding-left:px;
    &::before{
      position:absolute;
      left:px;
      top:;
      content:"";
      width:px;
      height:px;
      background:#FBFF;
    }
  }
}
.row{
  width:%;
  height:px;
  display:flex;
  flex-flow: row nowrap;
  justify-content: space-between;
  align-items: center;
  padding: 10px;
  .item_{
    flex:;
    width:%;
    height:%;
    display:flex;
    justify-content: center;
    align-items: center;
    .picwrapper{
      width:%;
      height:px;
      display:flex;
      justify-content: space-between;
      align-items: center;
      padding: 50px;
      .initem{
        width:px;
        height:px;
        box-shadow: 0 10px 10px rgba(255,255,255,.4);
        border-radius:px;
        overflow: hidden;
        position: relative;
        img{
          width:px;
          height:px;
          border-radius:px;
        }
        .intitle{
          position: absolute;
          font-size:px;
          font-weight: bold;
          bottom:px;
          text-align: center;
          width:%;
          color:#fff;
          text-shadow:px 0px 30px #023b92;
          letter-spacing:px;
        }
      }
    }
    .detailwrapper{
      width:%;
      height:px;
      padding: 50px;
      .dtop{
        overflow: hidden;
        img{
          transform: translate(-%,0);
        }
      }
      .btmwrapper{
        display:flex;
        width:%;
        height:px;
        margin-top:px;
        .left{
          flex-basis:px;
          img{
            position: relative;
            top:%;
            transform: translate(,-50%);
            width:px;
            height:px;
          }
        }
        .right{
          flex:;
          box-shadow: rgba(,255,255,.9) 0 0 20px inset;
          padding:px;
          box-sizing: border-box;
          display:flex;
          justify-content: space-between;
          .content{
            width:%;
            display:flex;
            justify-content: space-between;
            align-items: center;
            .listdetailwrapper{
              width:px;
              height:auto;
              .listtop{
                width:px;
                ::v-deep .multiselect--active{
                  .multiselect__select{
                    z-index:;
                  }
                  .multiselect__input{
                    color:#fff !important;
                  }
                }
                ::v-deep .multiselect{
                  min-height:px;
                  font-size:px !important;
                  .multiselect__select{
                    width:px;
                    height:px;
                    line-height:px;
                    background: #FFDC;
                    border-radius:px;
                    margin-top:px;
                    &:before{
                      border-width:px 18px 0;
                    }
                  }
                  .multiselect__tags{
                    min-height:px;
                    font-size:px;
                    line-height:px;
                    background:#B6CD2;
                    .multiselect__input{
                      min-height:px;
                      line-height:px;
                      font-size:px;
                      background:#B6CD2;
                      color:#fff !important;
                    }
                    .multiselect__single{
                      min-height:px;
                      line-height:px;
                      font-size:px;
                      background:none;
                      color:#fff;
                    }
                  }
                  .multiselect__content-wrapper{
                    max-height:px !important;
                    .multiselect__option{
                      min-height:px;
                      line-height:px;
                    }
                  }
                }
                ::v-deep .multiselect__option--highlight{
                  background:#aaa;
                }
              }
              .listwrapper{
                width:%;
                height:px;
                overflow-y:scroll;
                -webkit-overflow-scrolling : touch;
                &::-webkit-scrollbar { width: !important }
                .coloractive{
                  color:#FFDC !important;
                }
                .listitem{
                  height:px;
                  font-size:px;
                  line-height:px;
                  color:#fff;
                  padding: 20px;
                  box-sizing: border-box;
                  text-overflow: ellipsis;
                  overflow: hidden;
                  white-space: nowrap;
                  width:%;
                  span{
                    font-size:px;
                    display: inline-block;
                    height:px;
                    float:right;
                    line-height:px;
                    color:#FFDC;
                    margin-right:px
                  }
                  &:hover{
                    background:rgba(,255,255,0.3);
                    color:#FFDC
                  }
                }
              }
            }
            .detail{
              flex:;
              padding:px;
              box-sizing: border-box;
              overflow-y: scroll;
              &::-webkit-scrollbar{
                width:;
              }
              .editor{
                background:none;
                font-size:px;
                color:#fff;
              }
              .img-wrapper{
                width:px;
                hieght:px;
                margin: auto;
                background:url("../assets/pic_rczc_ym.png") no-repeat center right;
                .img{
                  width:px;
                  height:px;
                }
              }
            }
          }

          .pdf-wrapper{
            width:%;
            display:flex;
            justify-content: center;
            align-items: center;
            .decit{
              font-size:px;
              z-index:;
            }
          }
        }
      }
    }
  }
}
</style>

说一下这个项目, 这个项目中使用 turnjs 的时候

只能 倒翻书, 不能正翻书, direction:“rtl”, 只能rtl才生效, 如果是 ltr 就是出错,无效果

后来找到了另外一个解决办法 v-touch 就是解决的办法

首先 禁止掉 turnjs 的翻页效果

			//这段代码就是禁止 turnjs 的翻书效果
            $("#magazine").bind("start",function(e,p,c){
              if(c == "tl"||c == 'tr'){
                e.preventDefault();
              }
            })

然后, 使用 v-touch 监听 左右滑动

//书翻页
changeindexleft(index){
  this.$nextTick(()=>{
    if(index ==){
      $("#magazine").turn("next")
    }
  })
},
changeindexright(index){
  this.$nextTick(()=>{
    if(index ==){
      $("#magazine").turn("previous")
    }
  })
},

这样书就可以 前后翻动了 解决了 turnjs 只能 倒翻书的问题

还有一个问题, 就是 因为,本页面会加载不同的pdf 文件, 而 turnjs 初始化后 $(“#magazine1”).turn();会在 其中添加很多其它的标记, 如果在 $(“#margazine1”).turn()初始化完成之后 , 再执行一次 $(“#margazine1”).turn();就会形成无限的嵌套,导至显示出错。

最初我使用的是 vue 的数据改变来 更改 pdf 图片的显示, 就踩了上面的坑, 后来经过分析, 我在代码中使用了 jquery 的方法来改变数据

上面的代码中

以上便是我使用 vue pdf-dist 和turnjs做翻页的心得