目录
- 首先 安装 psfjs-dist
- vue中安装jquery的方法
- 下载trunjs
pdfjs-dist 的工作原理:把获取到的 pbf 的文件的数据流, 利用 canvas转换成图片
turnjs 把多个元素做成翻书的特效
我接手了一个展示大屏的项目, 其中有一个地方,就是要以翻书的形式来预览 pdf文件
如图
首先 安装 psfjs-dist
npm install --save pdfjs-dist
turnjs 是jquery的项目, 所以, 我们要在vuejs中安装 jquery
vue中安装jquery的方法
npm install jquery --save
然后在 vue.config.js中配置
module.exports = { | |
chainWebpack: config => { | |
config.plugin('provide').use(webpack.ProvidePlugin, [{ | |
$: 'jquery', | |
jquery: 'jquery', | |
jQuery: 'jquery', | |
'window.jQuery': 'jquery' | |
}]) | |
} |
下载trunjs
我写这个笔记的时候, 官网好像下载出错了,我找到了另一种下载的方法
把官网的示例随便打开了个, 找到 上图中的地址
这样也可以得到我们想要的 trunjs库
上面是安装, 下面我们开始使用
<div class="body-content" style="height:px;"> | |
<v-touch @swipeleft="changeindexleft()" @swiperight="changeindexright(1)"> | |
<div id="magazine" style="height:850px;width:1200px;margin-left:0 !important;"> | |
<!-- 这里的 magazine 就是翻页组件的容器 --> | |
</div> | |
</v-touch> | |
<!-- 这里的 docview 是用来存放 pdf转成图片时,所用到的 canvas 标签的--> | |
<div style="margin: auto; text-align: center; display: none"> | |
<div id="docView" ref="docView1"></div> | |
</div> | |
</div> |
代码部份
引入 jquery 和 turnjs
import $ from "jquery"; | |
import * as PDFJS from "pdfjs-dist"; | |
import turn from "../utils/lib/turn.js" | |
//初始化pdf插件 | |
/* | |
** @param fileUrl pdf有效的查看地址 | |
** (、线上地址(如:http://www.xxx.com) | |
**、本地public地址(例如:/static/view.pdf)) | |
** @param pdfPicturePath pdf转化的图片地址-用于放大查看所有pdf图片 | |
*/ | |
readPdf(fileUrl,index) { | |
//这个index 是我代码中要用的, 如果单独使用的话, 可以不要 index 这个参数 | |
let self = this; | |
let loadingTask = PDFJS.getDocument(fileUrl); //读取pdf文件 | |
console.log(loadingTask, '-----------loadingTask'); | |
loadingTask.promise | |
.then(function (pdf) { | |
if (pdf) { | |
// pdf 总页数 | |
const pageNum = pdf.numPages; | |
for (let i =; i <= pageNum; i++) { | |
// 生成每页 pdf 的 canvas | |
const canvas = document.createElement('canvas'); | |
canvas.id = 'page'+index+'Num' + i; | |
canvas.className = 'h'+index; | |
// 将 canvas 添加到 dom 中,docView(存放canvas的div) | |
let docViewX = "docView"+index; | |
console.log(docViewX); | |
self.$refs[docViewX].append(canvas); | |
//getContext() 方法返回一个用于在画布上绘图的环境。 | |
const context = canvas.getContext('d'); | |
self.openPage(pdf, i, context); | |
} | |
setTimeout(() => { | |
self.exportImg(self,index); | |
},); | |
} | |
}) | |
.catch(function (reason) { | |
console.error('Error: ' + reason); | |
}); | |
}, | |
//pdf转成canvas | |
/* | |
** @param loading pdf生成图片时的加载状态 | |
** @param scale 控制 canvas显示的大小 | |
*/ | |
openPage(pdfFile, pageNumber, context) { | |
let that = this; | |
pdfFile.getPage(pageNumber).then(function (page) { | |
// reference canvas via context | |
let viewport = page.getViewport({scale:}); | |
let scale =( / viewport.height).toFixed(2) //这里根把自已的项目需求,宽高进行调整 | |
let viewport = page.getViewport({scale:scale}); | |
let canvas = context.canvas; | |
canvas.width = viewport.width; | |
canvas.height = viewport.height; | |
canvas.style.width = '%'; | |
canvas.style.height = '%'; | |
let renderContext = { | |
canvasContext: context, | |
viewport: viewport | |
}; | |
page.render(renderContext); | |
that.loading = false; | |
}); | |
return; | |
}, | |
//canvas转成图片(可根据具体情况,进行图片转化显示)这里我把所有图片的base存放在数组里面,方便放大查看,也可以直接把生成图片标签进行图片展示 | |
// 转图片 | |
exportImg(self,index) { | |
//let canvaslist= document.querySelectorAll('canvas'); | |
let canvaslist = document.getElementsByClassName("h"+index); | |
let pdfPicturePathX = "pdfPicturePath"+index; | |
this[pdfPicturePathX] = []; | |
//这里把所有的图片地址放入到 pdfPicturePath 数组中去 | |
for (let i =; i < canvaslist.length; i++) { | |
// let canvas = document.getElementById("pageNum" + (i +)); | |
// // 将 canvas 转成 base 格式的图片 | |
// let baseImgSrc = (canvas as any).toDataURL("image/png") | |
// const img = document.createElement("img") | |
// img.setAttribute('class', 'pdf-img'); | |
// img.src = baseImgSrc | |
// img.style.width = '%'; | |
// // 将图片挂载到 dom 中 | |
// (self.$refs as any).docView.append(img); | |
let canvasNode = document.getElementById('page'+index+'Num' + (i +)); | |
// 将 canvas 转成 base 格式的图片 | |
if(canvasNode){ | |
this[pdfPicturePathX].push({page: i +, pic: canvasNode.toDataURL('image/png'), name: i + 1}) | |
}else { | |
continue; | |
} | |
//console.log('--------------aaa-------------', this.pdfPicturePath); | |
} | |
//到上面就是把pdf文件转成 base格式的图片, 之后把它们存在 pdfPicturePath1的数组中 | |
this.$nextTick(()=>{ | |
if(index ==){ | |
if($("#magazine").children().length > 0){ | |
$("#magazine").turn("destroy"); | |
$("#magazine").children().remove(); | |
} | |
let magazine = $("#magazine1"); | |
this[pdfPicturePathX].forEach(i=>{ | |
magazine.append("<img src='"+i.pic+"'/>") | |
}); | |
//setTimeout(()=>{ | |
$("#magazine").turn({ | |
autoCenter: true, | |
elevation:, | |
acceleration: true, | |
//direction:"rtl", | |
// when: { | |
// turned: function() { | |
// //当前页 | |
// // console.log("Current view: ", $(this).turn("view")); | |
// // //总页数 | |
// // console.log( | |
// // "#magazine has " + $("#magazine").turn("pages") + " pages" | |
// // ); | |
// //$("#magazine").turn("hasPage",); | |
// //$("#magazine").turn("pages",); | |
// } | |
// } | |
}) | |
$("#magazine").turn("center"); | |
$("#magazine").turn("page"); | |
//console.log($("#magazine").turn("pages")); | |
$("#magazine").bind("start",function(e,p,c){ | |
if(c == "tl"||c == 'tr'){ | |
e.preventDefault(); | |
} | |
}) | |
//}, | |
} | |
}, | |
下面是我项目的一个完现代码
<template> | |
<div id="index" ref="appRef"> | |
<div class="bg"> | |
<dv-loading v-show="loading">Loading...</dv-loading> | |
<div v-show="!loading" class="host-body"> | |
<!-- 第一行--> | |
<div class="row"> | |
<div class="title-wrapper"> | |
<img src="../assets/pic_rczs_title.png"> | |
<fullscreen ref="fullscreen" style="float:right"></fullscreen> | |
</div> | |
</div> | |
<!-- 第二行 --> | |
<div class="row"> | |
<div class="item_"> | |
<div class="picwrapper" v-show="showfengmian"> | |
<div class="initem" v-if="categoryslist[]" @click="fengmianclick(1,0)"> | |
<img :src="categoryslist[].more.thumbnail"/> | |
<div class="intitle">{{categoryslist[].name}}</div> | |
</div> | |
<div class="initem" v-if="categoryslist[]" @click="fengmianclick(1,1)"> | |
<img :src="categoryslist[].more.thumbnail"/> | |
<div class="intitle">{{categoryslist[].name}}</div> | |
</div> | |
</div> | |
<div class="detailwrapper" v-show="!showfengmian"> | |
<div class="dtop"> | |
<img src="../assets/pic_qyzc_shrcxzsy.png"/> | |
</div> | |
<div class="btmwrapper"> | |
<div class="left"> | |
<img src="../assets/icon_fanhui.png" @click="backtoshow()"/> | |
</div> | |
<div class="right"> | |
<div class="content" v-show="!showpdf"> | |
<div class="listdetailwrapper"> | |
<div class="listtop"> | |
<multiselect v-model="value" | |
placeholder="请选择" | |
open-direction="bottom" | |
:show-labels="false" | |
trackBy="id" | |
label="name" | |
@select="chooseSelect" | |
:options="selectoptions"> | |
</multiselect> | |
</div> | |
<div class="listwrapper"> | |
<div @click="chooselist(,index,item)" class="listitem" :class="selectItemIndex1 == index?'coloractive':''" v-for="(item,index) in selectList1" :key="item.id">{{item.name}}<span style="float: right" v-if="selectItemIndex1 == index"> 》</span></div> | |
</div> | |
</div> | |
<div class="detail" :style="{height:ispdf?'':'100%'}"> | |
<div v-if="!ispdf" class="markdown-body editor" v-html="articleDetail1.post_content"></div> | |
<div class="img-wrapper" v-if="ispdf" @click="pdfshowClick(1,articleDetail1.more.files)"> | |
<img class="img" src="../assets/pic_mrfm_wj@2x.png"/> | |
</div> | |
</div> | |
</div> | |
<div class="pdf-wrapper" v-show="showpdf"> | |
<div class="body-content" style="height:px;"> | |
<v-touch @swipeleft="changeindexleft()" @swiperight="changeindexright(1)"> | |
<div id="magazine" style="height:850px;width:1200px;margin-left:0 !important;"> | |
<!-- <div v-for="(item, index) in pdfPicturePath" :key="`test_${index}`">--> | |
<!-- <div>--> | |
<!-- <v-touch @swipeleft="changeindexleft()" @swiperight="changeindexright(1)">--> | |
<!-- <img :src="item.pic" class="pdf_pic" />--> | |
<!-- </v-touch>--> | |
<!-- </div>--> | |
<!-- </div>--> | |
</div> | |
</v-touch> | |
<div style="margin: auto; text-align: center; display: none"> | |
<div id="docView" ref="docView1"></div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class="item_"> | |
<div class="picwrapper" v-show="showfengmian"> | |
<div class="initem" v-if="categoryslist[]" @click="fengmianclick(2,2)"> | |
<img :src="categoryslist[].more.thumbnail"/> | |
<div class="intitle">{{categoryslist[].name}}</div> | |
</div> | |
<div class="initem" v-if="categoryslist[]" @click="fengmianclick(2,3)"> | |
<img :src="categoryslist[].more.thumbnail"/> | |
<div class="intitle">{{categoryslist[].name}}</div> | |
</div> | |
</div> | |
<div class="detailwrapper" v-show="!showfengmian"> | |
<div class="dtop"> | |
<img src="../assets/pic_qyzc_shrcxzsy.png"/> | |
</div> | |
<div class="btmwrapper"> | |
<div class="left"> | |
<img src="../assets/icon_fanhui.png" @click="backtoshow()"/> | |
</div> | |
<div class="right"> | |
<div class="content" v-show="!showpdf"> | |
<div class="listdetailwrapper"> | |
<div class="listtop"> | |
<multiselect v-model="value" | |
placeholder="请选择" | |
open-direction="bottom" | |
:show-labels="false" | |
trackBy="id" | |
label="name" | |
@select="chooseSelect" | |
:options="selectoptions"> | |
</multiselect> | |
</div> | |
<div class="listwrapper"> | |
<div @click="chooselist(,index,item)" class="listitem" :class="selectItemIndex2 == index?'coloractive':''" v-for="(item,index) in selectList2" :key="item.id">{{item.name}}<span style="float: right" v-if="selectItemIndex2 == index"> 》</span></div> | |
</div> | |
</div> | |
<div class="detail" :style="{height:ispdf?'':'100%'}"> | |
<div v-if="!ispdf" class="markdown-body editor" v-html="articleDetail2.post_content"></div> | |
<div class="img-wrapper" v-if="ispdf" @click="pdfshowClick(2,articleDetail2.more.files)"> | |
<img class="img" src="../assets/pic_mrfm_wj@2x.png"/> | |
</div> | |
</div> | |
</div> | |
<div class="pdf-wrapper" v-show="showpdf"> | |
<div class="body-content" style="height:px;"> | |
<v-touch @swipeleft="changeindexleft()" @swiperight="changeindexright(2)"> | |
<div id="magazine" style="height:850px;width:1200px;margin-left:0 !important;"> | |
<!-- <div v-for="(item, index) in pdfPicturePath" :key="`test_${index}`">--> | |
<!-- <div>--> | |
<!-- <v-touch @swipeleft="changeindexleft()" @swiperight="changeindexright(2)">--> | |
<!-- <img :src="item.pic" class="pdf_pic" />--> | |
<!-- </v-touch>--> | |
<!-- </div>--> | |
<!-- </div>--> | |
</div> | |
</v-touch> | |
<div style="margin: auto; text-align: center; display: none"> | |
<div id="docView" ref="docView2"></div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class="item_"> | |
<div class="picwrapper" v-show="showfengmian"> | |
<div class="initem" v-if="categoryslist[]" @click="fengmianclick(3,4)"> | |
<img :src="categoryslist[].more.thumbnail"/> | |
<div class="intitle">{{categoryslist[].name}}</div> | |
</div> | |
<div class="initem" v-if="categoryslist[]" @click="fengmianclick(3,5)"> | |
<img :src="categoryslist[].more.thumbnail"/> | |
<div class="intitle">{{categoryslist[].name}}</div> | |
</div> | |
</div> | |
<div class="detailwrapper" v-show="!showfengmian"> | |
<div class="dtop"> | |
<img src="../assets/pic_qyzc_shrcxzsy.png"/> | |
</div> | |
<div class="btmwrapper"> | |
<div class="left"> | |
<img src="../assets/icon_fanhui.png" @click="backtoshow()"/> | |
</div> | |
<div class="right"> | |
<div class="content" v-show="!showpdf"> | |
<div class="listdetailwrapper"> | |
<div class="listtop"> | |
<multiselect v-model="value" | |
placeholder="请选择" | |
open-direction="bottom" | |
:show-labels="false" | |
trackBy="id" | |
label="name" | |
@select="chooseSelect" | |
:options="selectoptions"> | |
</multiselect> | |
</div> | |
<div class="listwrapper"> | |
<div @click="chooselist(,index,item)" class="listitem" :class="selectItemIndex3 == index?'coloractive':''" v-for="(item,index) in selectList3" :key="item.id">{{item.name}}<span style="float: right" v-if="selectItemIndex3 == index"> 》</span></div> | |
</div> | |
</div> | |
<div class="detail" :style="{height:ispdf?'':'100%'}"> | |
<div v-if="!ispdf" class="markdown-body editor" v-html="articleDetail3.post_content"></div> | |
<div class="img-wrapper" v-if="ispdf" @click="pdfshowClick(3,articleDetail3.more.files)"> | |
<img class="img" src="../assets/pic_mrfm_wj@2x.png"/> | |
</div> | |
</div> | |
</div> | |
<div class="pdf-wrapper" v-show="showpdf"> | |
<div class="body-content" style="height:px;"> | |
<v-touch @swipeleft="changeindexleft()" @swiperight="changeindexright(3)"> | |
<div id="magazine" style="height:850px;width:1200px;margin-left:0 !important;"> | |
<!-- <div v-for="(item, index) in pdfPicturePath" :key="`test_${index}`">--> | |
<!-- <div>--> | |
<!-- <v-touch @swipeleft="changeindexleft()" @swiperight="changeindexright(3)">--> | |
<!-- <img :src="item.pic" class="pdf_pic" />--> | |
<!-- </v-touch>--> | |
<!-- </div>--> | |
<!-- </div>--> | |
</div> | |
</v-touch> | |
<div style="margin: auto; text-align: center; display: none"> | |
<div id="docView" ref="docView3"></div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</template> | |
<script> | |
import drawMixin from "../utils/drawMixin"; | |
import "github-markdown-css/github-markdown.css" | |
import fullscreen from "@/views/fullscreen"; | |
import Multiselect from "vue-multiselect"; | |
import $ from "jquery"; | |
import * as PDFJS from "pdfjs-dist"; | |
import turn from "../utils/lib/turn.min.js" | |
import M from "../model/m"; | |
export default { | |
mixins: [ drawMixin ], | |
data() { | |
return { | |
categoryslist:[], //首页的分类列表, 一共有六个分类 | |
//下拉选择框 三个 | |
selectoptions:[ | |
], | |
selectoptions:[], | |
selectoptions:[], | |
//下拉选择框的值 三个 | |
value:{}, | |
value:{}, | |
value:{}, | |
//下拉选择后的列表 三个 | |
selectList:[], | |
//列表中选中的标记, 主要是为了显示 条目中的小箭头 | |
selectItemIndex:-1, | |
selectList:[], | |
selectItemIndex:-2, | |
selectList:[], | |
selectItemIndex:-3, | |
//标记pdf记号 | |
ispdf:false, | |
ispdf:false, | |
ispdf:false, | |
//showpdf div的标记 | |
showpdf:false, | |
showpdf:false, | |
showpdf:false, | |
showfengmian:true, | |
showfengmian:true, | |
showfengmian:true, | |
articleDetail:{}, | |
articleDetail:{}, | |
articleDetail:{}, | |
pdfPicturePath: [], // pdf转化的图片地址 | |
pdfPicturePath: [], // pdf转化的图片地址 | |
pdfPicturePath: [], // pdf转化的图片地址 | |
loading:true, | |
} | |
}, | |
components: { | |
fullscreen, | |
Multiselect | |
}, | |
computed:{ | |
}, | |
mounted() { | |
this.initData(); | |
//this.timeFn() | |
//this.readPdf("bbb.pdf") | |
this.cancelLoading(); | |
this.$refs.fullscreen.toggleFullScreen(); | |
}, | |
beforeDestroy () { | |
}, | |
methods: { | |
chooseSelect(selectoption){ | |
this.getSelectList(selectoption,); | |
}, | |
chooseSelect(selectoption){ | |
this.getSelectList(selectoption,); | |
}, | |
chooseSelect(selectoption){ | |
this.getSelectList(selectoption,); | |
}, | |
initData(){ | |
//得到首页的图片列表 | |
M.getCategorys().then(res=>{ | |
this.categoryslist = res.data.categories; | |
}) | |
}, | |
//封面被点击 | |
fengmianclick(index,categoryslistindex){ | |
console.log(index,categoryslistindex); | |
//index 表示是哪一列中的(本屏一共有三列) | |
//categoryslistindex 被点击的在 categoryslist中的index | |
let showfengmianX = "showfengmian"+index; | |
this[showfengmianX] = false; | |
let thecategory = this.categoryslist[categoryslistindex]; | |
M.getCategorys(thecategory.id).then(res=>{ | |
let selectoptions = res.data.categories; | |
let selectoptionsX = "selectoptions"+index; | |
this[selectoptionsX] = selectoptions; | |
let valueX = "value"+index; | |
this[valueX] = selectoptions[]; | |
//这里要显示默认的项的信息 | |
this.getSelectList(selectoptions[],index); | |
}) | |
}, | |
getSelectList(value,index){ | |
//index表示第几列的 | |
let params = { | |
category_id:value.id | |
} | |
M.getselectLists(params).then(res=>{ | |
console.log(res); | |
let selectListX = "selectList"+index; | |
let selectlist = res.data.map(i=>{ | |
i.name=i.post_title; | |
if(i.tag ==){ | |
i.type = "txt" | |
}else if(i.tag ==){ | |
i.type = "pdf"; | |
} | |
return i; | |
}); | |
this[selectListX] = selectlist; | |
let selectItemIndexX = "selectItemIndex"+index; | |
this[selectItemIndexX] =; | |
let theselectItem = selectlist[]; | |
this.getArticleDetail(theselectItem,index); | |
}) | |
}, | |
//通过文章id来显示文章的详情 | |
getArticleDetail(theselectItem,index){ | |
//index 第几列 | |
if(!theselectItem){ | |
let articleDetailX = "articleDetail"+index; | |
this[articleDetailX] = []; | |
return; | |
} | |
let ispdfX = "ispdf"+index; | |
let article_id = theselectItem.id; | |
this[ispdfX] = theselectItem.type == "pdf"?true:false | |
M.getArticleDetail(article_id).then(res=>{ | |
let articleDetailX = "articleDetail"+index; | |
this[articleDetailX] = res.data; | |
if(theselectItem.type == "pdf"){ | |
this.readPdf(res.data.more.files[].url,index); | |
//this.readPdf("bbb.pdf?"+Math.random(),index) | |
} | |
}) | |
}, | |
//回退 | |
backtoshow(index){ | |
//index 表示是哪一列中的(本屏一共有三列) | |
let showpdfX = "showpdf"+index; | |
//当 showpdfX == true是 一定是显示了pdf 的滑动页 | |
if(this[showpdfX]){ | |
this[showpdfX] = !this[showpdfX] | |
}else{ | |
//如果是showpdfX 是 false ,那就应该是退回上一级的页面 | |
let showfengmianX = "showfengmian"+index; | |
this[showfengmianX] = true; | |
} | |
}, | |
pdfshowClick(index,files){ | |
//index 表示是哪一列中的(本屏一共有三列) | |
let showpdfX = "showpdf"+index; | |
this[showpdfX] = true; | |
//是在这里加载pdf ,还是在列表中点击的时候加载pdf 可以测试一下哪个要好一点 | |
//this.readPdf("bbb.pdf",index) | |
}, | |
chooselist(index,listindex,item){ | |
//第一个index 表示是哪一列中的(本屏一共有三列) | |
//listindex 表示点击的是哪一条数据 | |
let selectItemIndexX = "selectItemIndex"+index; | |
this[selectItemIndexX] = listindex; | |
let selectListX = "selectList"+index; | |
//从selectListX中的数组中得到这条信息的具体内容,并标记是否是一个pdf文件 | |
//看后台的设计,这里可能是要请求接口的 | |
let ispdfX = "ispdf"+index; | |
this[ispdfX] = this[selectListX][listindex].type == "pdf"?true:false | |
this.getArticleDetail(item,index) | |
}, | |
//书翻页 | |
changeindexleft(index){ | |
this.$nextTick(()=>{ | |
if(index ==){ | |
$("#magazine").turn("next") | |
}else if(index ==){ | |
$("#magazine").turn("next") | |
}else if(index ==){ | |
$("#magazine").turn("next") | |
} | |
}) | |
}, | |
changeindexright(index){ | |
this.$nextTick(()=>{ | |
if(index ==){ | |
$("#magazine").turn("previous") | |
}else if(index ==){ | |
$("#magazine").turn("previous") | |
}else if(index ==){ | |
$("#magazine").turn("previous") | |
} | |
}) | |
}, | |
//初始化pdf插件 | |
/* | |
** @param fileUrl pdf有效的查看地址 | |
** (、线上地址(如:http://www.xxx.com) | |
**、本地public地址(例如:/static/view.pdf)) | |
** @param pdfPicturePath pdf转化的图片地址-用于放大查看所有pdf图片 | |
*/ | |
readPdf(fileUrl,index) { | |
let self = this; | |
if(index ==){ | |
let loadingTask = PDFJS.getDocument(fileUrl); //读取pdf文件 | |
console.log(loadingTask, '-----------loadingTask'); | |
loadingTask.promise | |
.then(function (pdf) { | |
if (pdf) { | |
// pdf 总页数 | |
const pageNum = pdf.numPages; | |
for (let i =; i <= pageNum; i++) { | |
// 生成每页 pdf 的 canvas | |
const canvas = document.createElement('canvas'); | |
canvas.id = 'page'+index+'Num' + i; | |
canvas.className = 'h'+index; | |
// 将 canvas 添加到 dom 中,docView(存放canvas的div) | |
let docViewX = "docView"+index; | |
console.log(docViewX); | |
self.$refs[docViewX].append(canvas); | |
//getContext() 方法返回一个用于在画布上绘图的环境。 | |
const context = canvas.getContext('d'); | |
self.openPage(pdf, i, context); | |
} | |
setTimeout(() => { | |
self.exportImg(self,index); | |
},); | |
} | |
}) | |
.catch(function (reason) { | |
console.error('Error: ' + reason); | |
}); | |
} | |
if(index ==){ | |
let loadingTask = PDFJS.getDocument(fileUrl); //读取pdf文件 | |
console.log(loadingTask, '-----------loadingTask'); | |
loadingTask.promise | |
.then(function (pdf) { | |
if (pdf) { | |
// pdf 总页数 | |
const pageNum = pdf.numPages; | |
for (let i =; i <= pageNum; i++) { | |
// 生成每页 pdf 的 canvas | |
const canvas = document.createElement('canvas'); | |
canvas.id = 'page'+index+'Num' + i; | |
canvas.className = 'h'+index; | |
// 将 canvas 添加到 dom 中,docView(存放canvas的div) | |
let docViewX = "docView"+index; | |
console.log(docViewX); | |
self.$refs[docViewX].append(canvas); | |
//getContext() 方法返回一个用于在画布上绘图的环境。 | |
const context = canvas.getContext('d'); | |
self.openPage(pdf, i, context); | |
} | |
setTimeout(() => { | |
self.exportImg(self,index); | |
},); | |
} | |
}) | |
.catch(function (reason) { | |
console.error('Error: ' + reason); | |
}); | |
} | |
if(index ==){ | |
let loadingTask = PDFJS.getDocument(fileUrl); //读取pdf文件 | |
console.log(loadingTask, '-----------loadingTask'); | |
loadingTask.promise | |
.then(function (pdf) { | |
if (pdf) { | |
// pdf 总页数 | |
const pageNum = pdf.numPages; | |
for (let i =; i <= pageNum; i++) { | |
// 生成每页 pdf 的 canvas | |
const canvas = document.createElement('canvas'); | |
canvas.id = 'page'+index+'Num' + i; | |
canvas.className = 'h'+index; | |
// 将 canvas 添加到 dom 中,docView(存放canvas的div) | |
let docViewX = "docView"+index; | |
console.log(docViewX); | |
self.$refs[docViewX].append(canvas); | |
//getContext() 方法返回一个用于在画布上绘图的环境。 | |
const context = canvas.getContext('d'); | |
self.openPage(pdf, i, context); | |
} | |
setTimeout(() => { | |
self.exportImg(self,index); | |
},); | |
} | |
}) | |
.catch(function (reason) { | |
console.error('Error: ' + reason); | |
}); | |
} | |
}, | |
//pdf转成canvas | |
/* | |
** @param loading pdf生成图片时的加载状态 | |
** @param scale 控制 canvas显示的大小 | |
** @param pdfPicturePath pdf转化的图片地址-用于放大查看所有pdf图片 | |
*/ | |
openPage(pdfFile, pageNumber, context) { | |
let that = this; | |
pdfFile.getPage(pageNumber).then(function (page) { | |
// reference canvas via context | |
let viewport = page.getViewport({scale:}); | |
let scale =( / viewport.height).toFixed(2) | |
let viewport = page.getViewport({scale:scale}); | |
let canvas = context.canvas; | |
canvas.width = viewport.width; | |
canvas.height = viewport.height; | |
canvas.style.width = '%'; | |
canvas.style.height = '%'; | |
let renderContext = { | |
canvasContext: context, | |
viewport: viewport | |
}; | |
page.render(renderContext); | |
that.loading = false; | |
}); | |
return; | |
}, | |
//canvas转成图片(可根据具体情况,进行图片转化显示)这里我把所有图片的base存放在数组里面,方便放大查看,也可以直接把生成图片标签进行图片展示 | |
// 转图片 | |
exportImg(self,index) { | |
//let canvaslist= document.querySelectorAll('canvas'); | |
let canvaslist = document.getElementsByClassName("h"+index); | |
let pdfPicturePathX = "pdfPicturePath"+index; | |
this[pdfPicturePathX] = []; | |
//这里把所有的图片地址放入到 pdfPicturePath 数组中去 | |
for (let i =; i < canvaslist.length; i++) { | |
// let canvas = document.getElementById("pageNum" + (i +)); | |
// // 将 canvas 转成 base 格式的图片 | |
// let baseImgSrc = (canvas as any).toDataURL("image/png") | |
// const img = document.createElement("img") | |
// img.setAttribute('class', 'pdf-img'); | |
// img.src = baseImgSrc | |
// img.style.width = '%'; | |
// // 将图片挂载到 dom 中 | |
// (self.$refs as any).docView.append(img); | |
let canvasNode = document.getElementById('page'+index+'Num' + (i +)); | |
// 将 canvas 转成 base 格式的图片 | |
if(canvasNode){ | |
this[pdfPicturePathX].push({page: i +, pic: canvasNode.toDataURL('image/png'), name: i + 1}) | |
}else { | |
continue; | |
} | |
//console.log('--------------aaa-------------', this.pdfPicturePath); | |
} | |
this.$nextTick(()=>{ | |
if(index ==){ | |
if($("#magazine").children().length > 0){ | |
$("#magazine").turn("destroy"); | |
$("#magazine").children().remove(); | |
} | |
let magazine = $("#magazine1"); | |
this[pdfPicturePathX].forEach(i=>{ | |
magazine.append("<img src='"+i.pic+"'/>") | |
}); | |
//setTimeout(()=>{ | |
$("#magazine").turn({ | |
autoCenter: true, | |
elevation:, | |
acceleration: true, | |
//direction:"rtl", | |
// when: { | |
// turned: function() { | |
// //当前页 | |
// // console.log("Current view: ", $(this).turn("view")); | |
// // //总页数 | |
// // console.log( | |
// // "#magazine has " + $("#magazine").turn("pages") + " pages" | |
// // ); | |
// //$("#magazine").turn("hasPage",); | |
// //$("#magazine").turn("pages",); | |
// } | |
// } | |
}) | |
$("#magazine").turn("center"); | |
$("#magazine").turn("page"); | |
//console.log($("#magazine").turn("pages")); | |
$("#magazine").bind("start",function(e,p,c){ | |
if(c == "tl"||c == 'tr'){ | |
e.preventDefault(); | |
} | |
}) | |
//},) | |
} | |
if(index ==){ | |
if($("#magazine").children().length > 0){ | |
$("#magazine").turn("destroy"); | |
$("#magazine").children().remove(); | |
} | |
let magazine = $("#magazine2"); | |
this[pdfPicturePathX].forEach(i=>{ | |
magazine.append("<div><img src='"+i.pic+"'/></div>") | |
}); | |
$("#magazine").turn("center"); | |
$("#magazine").turn("page"); | |
$("#magazine").turn({ | |
autoCenter: true, | |
acceleration: true, | |
//direction:"rtl", | |
when: { | |
turned: function() { | |
//当前页 | |
// console.log("Current view: ", $(this).turn("view")); | |
// //总页数 | |
// console.log( | |
// "#magazine has " + $("#magazine").turn("pages") + " pages" | |
// ); | |
//$("#magazine").turn("hasPage",); | |
//$("#magazine").turn("pages",); | |
} | |
} | |
}) | |
$("#magazine").bind("start",function(e,p,c){ | |
if(c == "tl"||c == 'tr'){ | |
e.preventDefault(); | |
} | |
}) | |
} | |
if(index ==){ | |
if($("#magazine").children().length > 0){ | |
$("#magazine").turn("destroy"); | |
$("#magazine").children().remove(); | |
} | |
let magazine = $("#magazine3"); | |
this[pdfPicturePathX].forEach(i=>{ | |
magazine.append("<div><img src='"+i.pic+"'/></div>") | |
}); | |
$("#magazine").turn("center"); | |
$("#magazine").turn("page"); | |
$("#magazine").turn({ | |
autoCenter: true, | |
acceleration: true, | |
//direction:"ltr", | |
when: { | |
turned: function() { | |
//当前页 | |
// console.log("Current view: ", $(this).turn("view")); | |
// //总页数 | |
// console.log( | |
// "#magazine has " + $("#magazine").turn("pages") + " pages" | |
// ); | |
//$("#magazine").turn("hasPage",); | |
//$("#magazine").turn("pages",); | |
} | |
} | |
}) | |
$("#magazine").bind("start",function(e,p,c){ | |
if(c == "tl"||c == 'tr'){ | |
e.preventDefault(); | |
} | |
}) | |
} | |
}) | |
}, | |
cancelLoading() { | |
setTimeout(() => { | |
this.loading = false | |
},) | |
} | |
} | |
} | |
</script> | |
<style src="vue-multiselect/dist/vue-multiselect.min.css"></style> | |
<style lang="scss" scoped> | |
@import '../assets/scss/index.scss'; | |
.row{ | |
margin-top:px; | |
.title-wrapper{ | |
position:relative; | |
padding-left:px; | |
&::before{ | |
position:absolute; | |
left:px; | |
top:; | |
content:""; | |
width:px; | |
height:px; | |
background:#FBFF; | |
} | |
} | |
} | |
.row{ | |
width:%; | |
height:px; | |
display:flex; | |
flex-flow: row nowrap; | |
justify-content: space-between; | |
align-items: center; | |
padding: 10px; | |
.item_{ | |
flex:; | |
width:%; | |
height:%; | |
display:flex; | |
justify-content: center; | |
align-items: center; | |
.picwrapper{ | |
width:%; | |
height:px; | |
display:flex; | |
justify-content: space-between; | |
align-items: center; | |
padding: 50px; | |
.initem{ | |
width:px; | |
height:px; | |
box-shadow: 0 10px 10px rgba(255,255,255,.4); | |
border-radius:px; | |
overflow: hidden; | |
position: relative; | |
img{ | |
width:px; | |
height:px; | |
border-radius:px; | |
} | |
.intitle{ | |
position: absolute; | |
font-size:px; | |
font-weight: bold; | |
bottom:px; | |
text-align: center; | |
width:%; | |
color:#fff; | |
text-shadow:px 0px 30px #023b92; | |
letter-spacing:px; | |
} | |
} | |
} | |
.detailwrapper{ | |
width:%; | |
height:px; | |
padding: 50px; | |
.dtop{ | |
overflow: hidden; | |
img{ | |
transform: translate(-%,0); | |
} | |
} | |
.btmwrapper{ | |
display:flex; | |
width:%; | |
height:px; | |
margin-top:px; | |
.left{ | |
flex-basis:px; | |
img{ | |
position: relative; | |
top:%; | |
transform: translate(,-50%); | |
width:px; | |
height:px; | |
} | |
} | |
.right{ | |
flex:; | |
box-shadow: rgba(,255,255,.9) 0 0 20px inset; | |
padding:px; | |
box-sizing: border-box; | |
display:flex; | |
justify-content: space-between; | |
.content{ | |
width:%; | |
display:flex; | |
justify-content: space-between; | |
align-items: center; | |
.listdetailwrapper{ | |
width:px; | |
height:auto; | |
.listtop{ | |
width:px; | |
::v-deep .multiselect--active{ | |
.multiselect__select{ | |
z-index:; | |
} | |
.multiselect__input{ | |
color:#fff ; | |
} | |
} | |
::v-deep .multiselect{ | |
min-height:px; | |
font-size:px ; | |
.multiselect__select{ | |
width:px; | |
height:px; | |
line-height:px; | |
background: #FFDC; | |
border-radius:px; | |
margin-top:px; | |
&:before{ | |
border-width:px 18px 0; | |
} | |
} | |
.multiselect__tags{ | |
min-height:px; | |
font-size:px; | |
line-height:px; | |
background:#B6CD2; | |
.multiselect__input{ | |
min-height:px; | |
line-height:px; | |
font-size:px; | |
background:#B6CD2; | |
color:#fff ; | |
} | |
.multiselect__single{ | |
min-height:px; | |
line-height:px; | |
font-size:px; | |
background:none; | |
color:#fff; | |
} | |
} | |
.multiselect__content-wrapper{ | |
max-height:px ; | |
.multiselect__option{ | |
min-height:px; | |
line-height:px; | |
} | |
} | |
} | |
::v-deep .multiselect__option--highlight{ | |
background:#aaa; | |
} | |
} | |
.listwrapper{ | |
width:%; | |
height:px; | |
overflow-y:scroll; | |
-webkit-overflow-scrolling : touch; | |
&::-webkit-scrollbar { width: } | |
.coloractive{ | |
color:#FFDC ; | |
} | |
.listitem{ | |
height:px; | |
font-size:px; | |
line-height:px; | |
color:#fff; | |
padding: 20px; | |
box-sizing: border-box; | |
text-overflow: ellipsis; | |
overflow: hidden; | |
white-space: nowrap; | |
width:%; | |
span{ | |
font-size:px; | |
display: inline-block; | |
height:px; | |
float:right; | |
line-height:px; | |
color:#FFDC; | |
margin-right:px | |
} | |
&:hover{ | |
background:rgba(,255,255,0.3); | |
color:#FFDC | |
} | |
} | |
} | |
} | |
.detail{ | |
flex:; | |
padding:px; | |
box-sizing: border-box; | |
overflow-y: scroll; | |
&::-webkit-scrollbar{ | |
width:; | |
} | |
.editor{ | |
background:none; | |
font-size:px; | |
color:#fff; | |
} | |
.img-wrapper{ | |
width:px; | |
hieght:px; | |
margin: auto; | |
background:url("../assets/pic_rczc_ym.png") no-repeat center right; | |
.img{ | |
width:px; | |
height:px; | |
} | |
} | |
} | |
} | |
.pdf-wrapper{ | |
width:%; | |
display:flex; | |
justify-content: center; | |
align-items: center; | |
.decit{ | |
font-size:px; | |
z-index:; | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
</style> |
说一下这个项目, 这个项目中使用 turnjs 的时候
只能 倒翻书, 不能正翻书, direction:“rtl”, 只能rtl才生效, 如果是 ltr 就是出错,无效果
后来找到了另外一个解决办法 v-touch 就是解决的办法
首先 禁止掉 turnjs 的翻页效果
//这段代码就是禁止 turnjs 的翻书效果 | |
$("#magazine").bind("start",function(e,p,c){ | |
if(c == "tl"||c == 'tr'){ | |
e.preventDefault(); | |
} | |
}) |
然后, 使用 v-touch 监听 左右滑动
//书翻页 | |
changeindexleft(index){ | |
this.$nextTick(()=>{ | |
if(index ==){ | |
$("#magazine").turn("next") | |
} | |
}) | |
}, | |
changeindexright(index){ | |
this.$nextTick(()=>{ | |
if(index ==){ | |
$("#magazine").turn("previous") | |
} | |
}) | |
}, |
这样书就可以 前后翻动了 解决了 turnjs 只能 倒翻书的问题
还有一个问题, 就是 因为,本页面会加载不同的pdf 文件, 而 turnjs 初始化后 $(“#magazine1”).turn();会在 其中添加很多其它的标记, 如果在 $(“#margazine1”).turn()初始化完成之后 , 再执行一次 $(“#margazine1”).turn();就会形成无限的嵌套,导至显示出错。
最初我使用的是 vue 的数据改变来 更改 pdf 图片的显示, 就踩了上面的坑, 后来经过分析, 我在代码中使用了 jquery 的方法来改变数据
上面的代码中
以上便是我使用 vue pdf-dist 和turnjs做翻页的心得