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

本文介绍了如何在Vue项目中利用pdfjs-dist将PDF文件转换为图片,并结合turnjs创建翻书效果。在解决过程中,详细讲述了安装pdfjs-dist和turnjs的步骤,以及在Vue中使用jQuery的注意事项。此外,还分享了在使用turnjs时遇到的正向翻页问题及v-touch的解决方案,以及处理多个PDF文件时避免turnjs初始化错误的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A黄俊辉A

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值