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

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

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

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

首先 安装 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/ 官网下载
我写这个笔记的时候, 官网好像下载出错了,我找到了另一种下载的方法

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

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

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

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

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

       <div class="body-content">
                      <v-touch @swipeleft="changeindexleft(1)" @swiperight="changeindexright(1)">
                      <div id="magazine1">
                        <!-- 这里的 magazine1  就是翻页组件的容器 -->
                      </div>
                      </v-touch>
                          <!-- 这里的 docview1 是用来存放 pdf转成图片时,所用到的 canvas 标签的-->
                      <div>
                        <div id="docView1" ref="docView1"></div>
                      </div>
                    </div>

代码部份

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

引入 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="https://www.jb51.net/assets/pic_rczs_title1.png">
<fullscreen ref="fullscreen"></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=""/>
</div>
<div class="btmwrapper">
<div class="left">
<img src="" @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 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=""/>
</div>
</div>
</div>
<div class="pdf-wrapper"  v-show="showpdf1">
<div class="body-content">
<v-touch @swipeleft="changeindexleft(1)" @swiperight="changeindexright(1)">
<div id="magazine1">
<!--                        <div v-for="(item, index) in pdfPicturePath1" :key="`test_${index}`">-->
<!--                          <div>-->
<!--                            <v-touch @swipeleft="changeindexleft(1)" @swiperight="changeindexright(1)">-->
<!--                            <img :src=""/>
</div>
<div class="btmwrapper">
<div class="left">
<img src="" @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 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=""/>
</div>
</div>
</div>
<div class="pdf-wrapper"  v-show="showpdf2">
<div class="body-content">
<v-touch @swipeleft="changeindexleft(2)" @swiperight="changeindexright(2)">
<div id="magazine2">
<!--                        <div v-for="(item, index) in pdfPicturePath2" :key="`test_${index}`">-->
<!--                          <div>-->
<!--                            <v-touch @swipeleft="changeindexleft(2)" @swiperight="changeindexright(2)">-->
<!--                              <img :src=""/>
</div>
<div class="btmwrapper">
<div class="left">
<img src="" @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 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=""/>
</div>
</div>
</div>
<div class="pdf-wrapper"  v-show="showpdf3">
<div class="body-content">
<v-touch @swipeleft="changeindexleft(3)" @swiperight="changeindexright(3)">
<div id="magazine3">
<!--                        <div v-for="(item, index) in pdfPicturePath3" :key="`test_${index}`">-->
<!--                          <div>-->
<!--                            <v-touch @swipeleft="changeindexleft(3)" @swiperight="changeindexright(3)">-->
<!--                              <img :src="") 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>

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

说一下这个项目, 这个项目中使用 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中使用pdfjs-dist + turnjs实现页面的翻书浏览功能

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

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

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。