vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > vue页面翻书浏览

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

作者:A黄俊辉A

这篇文章主要介绍了vue中使用pdfjs-dist + turnjs实现页面的翻书浏览,通过本文学习我们知道了pdfjs-dist 的工作原理是把获取到的 pbf 的文件的数据流, 利用 canvas转换成图片,本文通过实例代码详解讲解,需要的朋友可以参考下

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:850px;">
                      <v-touch @swipeleft="changeindexleft(1)" @swiperight="changeindexright(1)">
                      <div id="magazine1" style="height:850px;width:1200px;margin-left:0 !important;">
                        <!-- 这里的 magazine1  就是翻页组件的容器 -->
                      </div>
                      </v-touch>
                          <!-- 这里的 docview1 是用来存放 pdf转成图片时,所用到的 canvas 标签的-->
                      <div style="margin: 0 auto; text-align: center; display: none">
                        <div id="docView1" 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有效的查看地址
     **				(1、线上地址(如:http://www.xxx.com)
     **				2、本地public地址(例如:/static/view.pdf))
     ** @param  pdfPicturePath1 pdf转化的图片地址-用于放大查看所有pdf图片
     */
    readPdf(fileUrl,index) {
    	//这个index 是我代码中要用的, 如果单独使用的话, 可以不要 index 这个参数
      let self = this;
        let loadingTask1 = PDFJS.getDocument(fileUrl);  //读取pdf文件
        console.log(loadingTask1, '-----------loadingTask');
        loadingTask1.promise
            .then(function (pdf) {
              if (pdf) {
                // pdf 总页数
                const pageNum = pdf.numPages;
                for (let i = 1; 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('2d');
                  self.openPage(pdf, i, context);
                }
                setTimeout(() => {
                  self.exportImg(self,index);
                }, 2000);
              }
            })
            .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:1});
        let scale =(847 / viewport.height).toFixed(2)  //这里根把自已的项目需求,宽高进行调整
        let viewport1 = page.getViewport({scale:scale});

        let canvas = context.canvas;
        canvas.width = viewport1.width;
        canvas.height = viewport1.height;
        canvas.style.width = '100%';
        canvas.style.height = '100%';

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



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

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

          //setTimeout(()=>{

            $("#magazine1").turn({
              autoCenter: true,
              elevation: 50,
              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", 10);
              //     //$("#magazine").turn("pages", 1);
              //   }
              // }
            })
          $("#magazine1").turn("center");
          $("#magazine1").turn("page");

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


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

<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="row1">
          <div class="title-wrapper">
            <img src="../assets/pic_rczs_title1.png">
            <fullscreen ref="fullscreen" style="float:right"></fullscreen>
          </div>
        </div>
        <!-- 第二行 -->
        <div class="row2">
          <div class="item_3">
            <div class="picwrapper" v-show="showfengmian1">
              <div class="initem" v-if="categoryslist[0]" @click="fengmianclick(1,0)">
                <img :src="categoryslist[0].more.thumbnail"/>
                <div class="intitle">{{categoryslist[0].name}}</div>
              </div>
              <div class="initem"  v-if="categoryslist[1]" @click="fengmianclick(1,1)">
                <img :src="categoryslist[1].more.thumbnail"/>
                <div class="intitle">{{categoryslist[1].name}}</div>
              </div>
            </div>

            <div class="detailwrapper" v-show="!showfengmian1">
              <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(1)"/>
                </div>
                <div class="right">
                  <div class="content" v-show="!showpdf1">
                    <div class="listdetailwrapper">
                      <div class="listtop">
                        <multiselect v-model="value1"
                                     placeholder="请选择"
                                     open-direction="bottom"
                                     :show-labels="false"
                                     trackBy="id"
                                     label="name"
                                     @select="chooseSelect1"
                                     :options="selectoptions1">
                        </multiselect>
                      </div>
                      <div class="listwrapper">
                        <div @click="chooselist(1,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:ispdf1?'':'100%'}">
                      <div v-if="!ispdf1" class="markdown-body editor" v-html="articleDetail1.post_content"></div>
                      <div class="img-wrapper" v-if="ispdf1" @click="pdfshowClick(1,articleDetail1.more.files)">
                        <img class="img1" src="../assets/pic_mrfm_wj@2x.png"/>
                      </div>
                    </div>
                  </div>
                  <div class="pdf-wrapper"  v-show="showpdf1">
                    <div class="body-content" style="height:850px;">
                      <v-touch @swipeleft="changeindexleft(1)" @swiperight="changeindexright(1)">
                      <div id="magazine1" style="height:850px;width:1200px;margin-left:0 !important;">

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

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

            </div>
          </div>

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

            <div class="detailwrapper" v-show="!showfengmian2">
              <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(2)"/>
                </div>
                <div class="right">
                  <div class="content" v-show="!showpdf2">
                    <div class="listdetailwrapper">
                      <div class="listtop">
                        <multiselect v-model="value2"
                                     placeholder="请选择"
                                     open-direction="bottom"
                                     :show-labels="false"
                                     trackBy="id"
                                     label="name"
                                     @select="chooseSelect2"
                                     :options="selectoptions2">
                        </multiselect>
                      </div>
                      <div class="listwrapper">
                        <div @click="chooselist(2,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:ispdf2?'':'100%'}">
                      <div v-if="!ispdf2" class="markdown-body editor" v-html="articleDetail2.post_content"></div>
                      <div class="img-wrapper" v-if="ispdf2" @click="pdfshowClick(2,articleDetail2.more.files)">
                        <img class="img1" src="../assets/pic_mrfm_wj@2x.png"/>
                      </div>
                    </div>
                  </div>
                  <div class="pdf-wrapper"  v-show="showpdf2">
                    <div class="body-content" style="height:850px;">
                      <v-touch @swipeleft="changeindexleft(2)" @swiperight="changeindexright(2)">
                      <div id="magazine2" style="height:850px;width:1200px;margin-left:0 !important;">

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

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

            </div>
          </div>

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

            <div class="detailwrapper" v-show="!showfengmian3">
              <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(3)"/>
                </div>
                <div class="right">
                  <div class="content" v-show="!showpdf3">
                    <div class="listdetailwrapper">
                      <div class="listtop">
                        <multiselect v-model="value3"
                                     placeholder="请选择"
                                     open-direction="bottom"
                                     :show-labels="false"
                                     trackBy="id"
                                     label="name"
                                     @select="chooseSelect3"
                                     :options="selectoptions3">
                        </multiselect>
                      </div>
                      <div class="listwrapper">
                        <div @click="chooselist(3,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:ispdf3?'':'100%'}">
                      <div v-if="!ispdf3" class="markdown-body editor" v-html="articleDetail3.post_content"></div>
                      <div class="img-wrapper" v-if="ispdf3" @click="pdfshowClick(3,articleDetail3.more.files)">
                        <img class="img1" src="../assets/pic_mrfm_wj@2x.png"/>
                      </div>
                    </div>
                  </div>
                  <div class="pdf-wrapper"  v-show="showpdf3">
                    <div class="body-content" style="height:850px;">
                      <v-touch @swipeleft="changeindexleft(3)" @swiperight="changeindexright(3)">
                      <div id="magazine3" style="height:850px;width:1200px;margin-left:0 !important;">
<!--                        <div v-for="(item, index) in pdfPicturePath3" :key="`test_${index}`">-->
<!--                          <div>-->
<!--                            <v-touch @swipeleft="changeindexleft(3)" @swiperight="changeindexright(3)">-->
<!--                              <img :src="item.pic" class="pdf_pic" />-->
<!--                            </v-touch>-->
<!--                          </div>-->
<!--                        </div>-->
                      </div>
                      </v-touch>
                      <div style="margin: 0 auto; text-align: center; display: none">
                        <div id="docView3" 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:[],   //首页的分类列表, 一共有六个分类

      //下拉选择框 三个
      selectoptions1:[
      ],
      selectoptions2:[],
      selectoptions3:[],
      //下拉选择框的值 三个
      value1:{},
      value2:{},
      value3:{},
      //下拉选择后的列表 三个
      selectList1:[],
      //列表中选中的标记, 主要是为了显示 条目中的小箭头
      selectItemIndex1:-1,
      selectList2:[],
      selectItemIndex2:-2,
      selectList3:[],
      selectItemIndex3:-3,

      //标记pdf记号
      ispdf1:false,
      ispdf2:false,
      ispdf3:false,


      //showpdf div的标记
      showpdf1:false,
      showpdf2:false,
      showpdf3:false,


      showfengmian1:true,
      showfengmian2:true,
      showfengmian3:true,

      articleDetail1:{},
      articleDetail2:{},
      articleDetail3:{},



      pdfPicturePath1: [], // pdf转化的图片地址
      pdfPicturePath2: [], // pdf转化的图片地址
      pdfPicturePath3: [], // pdf转化的图片地址

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


  computed:{

  },


  mounted() {

    this.initData();


    //this.timeFn()

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



  },


  beforeDestroy () {

  },
  methods: {

    chooseSelect1(selectoption){
      this.getSelectList(selectoption,1);
    },

    chooseSelect2(selectoption){
      this.getSelectList(selectoption,2);
    },

    chooseSelect3(selectoption){
      this.getSelectList(selectoption,3);
    },

    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[0];
        //这里要显示默认的项的信息
        this.getSelectList(selectoptions[0],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 == 0){
            i.type = "txt"
          }else if(i.tag == 1){
            i.type = "pdf";
          }
          return i;
        });
        this[selectListX] = selectlist;
        let selectItemIndexX = "selectItemIndex"+index;
        this[selectItemIndexX] = 0;
        let theselectItem = selectlist[0];
        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[0].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 == 1){
          $("#magazine1").turn("next")
        }else if(index == 2){
          $("#magazine2").turn("next")
        }else if(index == 3){
          $("#magazine3").turn("next")
        }
      })


    },
    changeindexright(index){
      this.$nextTick(()=>{
        if(index == 1){
          $("#magazine1").turn("previous")
        }else if(index == 2){
          $("#magazine2").turn("previous")
        }else if(index == 3){
          $("#magazine3").turn("previous")
        }
      })

    },

//初始化pdf插件
    /*
     ** @param fileUrl pdf有效的查看地址
     **				(1、线上地址(如:http://www.xxx.com)
     **				2、本地public地址(例如:/static/view.pdf))
     ** @param  pdfPicturePath1 pdf转化的图片地址-用于放大查看所有pdf图片
     */
    readPdf(fileUrl,index) {
      let self = this;
      if(index == 1){
        let loadingTask1 = PDFJS.getDocument(fileUrl);  //读取pdf文件
        console.log(loadingTask1, '-----------loadingTask');
        loadingTask1.promise
            .then(function (pdf) {
              if (pdf) {
                // pdf 总页数
                const pageNum = pdf.numPages;
                for (let i = 1; 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('2d');
                  self.openPage(pdf, i, context);
                }
                setTimeout(() => {
                  self.exportImg(self,index);
                }, 2000);
              }
            })
            .catch(function (reason) {
              console.error('Error: ' + reason);
            });
      }
      if(index == 2){
        let loadingTask2 = PDFJS.getDocument(fileUrl);  //读取pdf文件
        console.log(loadingTask2, '-----------loadingTask');
        loadingTask2.promise
            .then(function (pdf) {
              if (pdf) {
                // pdf 总页数
                const pageNum = pdf.numPages;
                for (let i = 1; 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('2d');
                  self.openPage(pdf, i, context);
                }
                setTimeout(() => {
                  self.exportImg(self,index);
                }, 2000);
              }
            })
            .catch(function (reason) {
              console.error('Error: ' + reason);
            });
      }
      if(index == 3){
        let loadingTask3 = PDFJS.getDocument(fileUrl);  //读取pdf文件
        console.log(loadingTask3, '-----------loadingTask');
        loadingTask3.promise
            .then(function (pdf) {
              if (pdf) {
                // pdf 总页数
                const pageNum = pdf.numPages;
                for (let i = 1; 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('2d');
                  self.openPage(pdf, i, context);
                }
                setTimeout(() => {
                  self.exportImg(self,index);
                }, 2000);
              }
            })
            .catch(function (reason) {
              console.error('Error: ' + reason);
            });
      }


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

        let canvas = context.canvas;
        canvas.width = viewport1.width;
        canvas.height = viewport1.height;
        canvas.style.width = '100%';
        canvas.style.height = '100%';

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

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

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

          //setTimeout(()=>{

            $("#magazine1").turn({
              autoCenter: true,
              elevation: 50,
              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", 10);
              //     //$("#magazine").turn("pages", 1);
              //   }
              // }
            })
          $("#magazine1").turn("center");
          $("#magazine1").turn("page");

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



        }
        if(index == 2){
          if($("#magazine2").children().length > 0){
            $("#magazine2").turn("destroy");
            $("#magazine2").children().remove();
          }
          let magazine2 = $("#magazine2");
          this[pdfPicturePathX].forEach(i=>{
            magazine2.append("<div><img src='"+i.pic+"'/></div>")
          });
          $("#magazine2").turn("center");
          $("#magazine2").turn("page");
          $("#magazine2").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", 10);
                //$("#magazine").turn("pages", 1);
              }
            }
          })
          $("#magazine2").bind("start",function(e,p,c){
            if(c == "tl"||c == 'tr'){
              e.preventDefault();
            }
          })
        }

        if(index == 3){
          if($("#magazine3").children().length > 0){
            $("#magazine3").turn("destroy");
            $("#magazine3").children().remove();
          }
          let magazine3 = $("#magazine3");
          this[pdfPicturePathX].forEach(i=>{
            magazine3.append("<div><img src='"+i.pic+"'/></div>")
          });
          $("#magazine3").turn("center");
          $("#magazine3").turn("page");
          $("#magazine3").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", 10);
                //$("#magazine").turn("pages", 1);
              }
            }
          })
          $("#magazine3").bind("start",function(e,p,c){
            if(c == "tl"||c == 'tr'){
              e.preventDefault();
            }
          })
        }
      })
    },

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

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

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

.row1{
  margin-top:109px;
  .title-wrapper{
    position:relative;
    padding-left:177px;
    &::before{
      position:absolute;
      left:100px;
      top:0;
      content:"";
      width:20px;
      height:226px;
      background:#00FBFF;
    }
  }
}
.row2{
  width:100%;
  height:1584px;
  display:flex;
  flex-flow: row nowrap;
  justify-content: space-between;
  align-items: center;
  padding:0 10px;
  .item_3{
    flex:1;
    width:100%;
    height:100%;
    display:flex;
    justify-content: center;
    align-items: center;
    .picwrapper{
      width:100%;
      height:1183px;
      display:flex;
      justify-content: space-between;
      align-items: center;
      padding:0 50px;
      .initem{
        width:978px;
        height:1183px;
        box-shadow: 0 0 10px 10px rgba(255,255,255,.4);
        border-radius: 20px;
        overflow: hidden;
        position: relative;
        img{
          width:987px;
          height:1183px;
          border-radius: 20px;
        }
        .intitle{
          position: absolute;
          font-size:130px;
          font-weight: bold;
          bottom:143px;
          text-align: center;
          width:100%;
          color:#fff;
          text-shadow:0px 0px 30px #023b92;
          letter-spacing: 10px;
        }
      }
    }
    .detailwrapper{
      width:100%;
      height:1370px;
      padding:0 50px;
      .dtop{
        overflow: hidden;
        img{
          transform: translate(-2%,0);
        }
      }
      .btmwrapper{
        display:flex;
        width:100%;
        height:947px;
        margin-top:20px;
        .left{
          flex-basis: 144px;
          img{
            position: relative;
            top:50%;
            transform: translate(0,-50%);
            width:100px;
            height:100px;
          }
        }
        .right{
          flex:1;
          box-shadow: rgba(255,255,255,.9) 0 0 20px inset;
          padding:50px;
          box-sizing: border-box;
          display:flex;
          justify-content: space-between;
          .content{
            width:100%;
            display:flex;
            justify-content: space-between;
            align-items: center;
            .listdetailwrapper{
              width:885px;
              height:auto;
              .listtop{
                width:769px;
                ::v-deep .multiselect--active{
                  .multiselect__select{
                    z-index: 100;
                  }
                  .multiselect__input{
                    color:#fff !important;
                  }
                }
                ::v-deep .multiselect{
                  min-height:100px;
                  font-size: 56px !important;
                  .multiselect__select{
                    width: 100px;
                    height: 100px;
                    line-height: 76px;
                    background: #FFDC24;
                    border-radius: 50px;
                    margin-top: 10px;
                    &:before{
                      border-width: 25px 18px 0;
                    }
                  }
                  .multiselect__tags{
                    min-height: 100px;
                    font-size: 56px;
                    line-height: 100px;
                    background:#2B6CD2;
                    .multiselect__input{
                      min-height:100px;
                      line-height: 100px;
                      font-size:56px;
                      background:#2B6CD2;
                      color:#fff !important;
                    }
                    .multiselect__single{
                      min-height:100px;
                      line-height: 100px;
                      font-size:56px;
                      background:none;
                      color:#fff;
                    }
                  }
                  .multiselect__content-wrapper{
                    max-height: 700px !important;
                    .multiselect__option{
                      min-height: 100px;
                      line-height: 100px;
                    }
                  }
                }
                ::v-deep .multiselect__option--highlight{
                  background:#aaa;
                }
              }
              .listwrapper{
                width:100%;
                height:720px;
                overflow-y:scroll;
                -webkit-overflow-scrolling : touch;
                &::-webkit-scrollbar { width: 0 !important }
                .coloractive{
                  color:#FFDC24 !important;
                }
                .listitem{
                  height:110px;
                  font-size:56px;
                  line-height: 110px;
                  color:#fff;
                  padding:0 20px;
                  box-sizing: border-box;
                  text-overflow: ellipsis;
                  overflow: hidden;
                  white-space: nowrap;
                  width:95%;
                  span{
                    font-size:30px;
                    display: inline-block;
                    height:110px;
                    float:right;
                    line-height: 110px;
                    color:#FFDC24;
                    margin-right:40px
                  }
                  &:hover{
                    background:rgba(255,255,255,0.3);
                    color:#FFDC24
                  }
                }
              }
            }
            .detail{
              flex:1;
              padding:20px;
              box-sizing: border-box;
              overflow-y: scroll;
              &::-webkit-scrollbar{
                width:0;
              }
              .editor{
                background:none;
                font-size:50px;
                color:#fff;
              }
              .img-wrapper{
                width:500px;
                hieght:587px;
                margin:0 auto;
                background:url("../assets/pic_rczc_ym1.png") no-repeat center right;
                .img1{
                  width:441px;
                  height:587px;
                }
              }
            }
          }

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

说一下这个项目, 这个项目中使用 turnjs 的时候
只能 倒翻书, 不能正翻书, direction:“rtl”, 只能rtl才生效, 如果是 ltr 就是出错,无效果
后来找到了另外一个解决办法 v-touch 就是解决的办法
首先 禁止掉 turnjs 的翻页效果

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

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

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

这样书就可以 前后翻动了 解决了 turnjs 只能 倒翻书的问题
还有一个问题, 就是 因为,本页面会加载不同的pdf 文件, 而 turnjs 初始化后 $(“#magazine1”).turn();会在 其中添加很多其它的标记, 如果在 $(“#margazine1”).turn()初始化完成之后 , 再执行一次 $(“#margazine1”).turn();就会形成无限的嵌套,导至显示出错。
最初我使用的是 vue 的数据改变来 更改 pdf 图片的显示, 就踩了上面的坑, 后来经过分析, 我在代码中使用了 jquery 的方法来改变数据
上面的代码中

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

到此这篇关于vue中使用pdfjs-dist + turnjs实现页面的翻书浏览的文章就介绍到这了,更多相关vue页面的翻书浏览内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文