文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2022-11-13 19:06

关注

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插件
    
    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
    
    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插件
    
    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
    
    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页面的翻书浏览内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-前端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯