vue中使用pdfjs-dist?+?turnjs實(shí)現(xiàn)頁(yè)面的翻書(shū)瀏覽功能
pdfjs-dist 的工作原理:把獲取到的 pbf 的文件的數(shù)據(jù)流, 利用 canvas轉(zhuǎn)換成圖片
turnjs 把多個(gè)元素做成翻書(shū)的特效
我接手了一個(gè)展示大屏的項(xiàng)目, 其中有一個(gè)地方,就是要以翻書(shū)的形式來(lái)預(yù)覽 pdf文件
如圖
首先 安裝 psfjs-dist
npm install --save pdfjs-dist
turnjs 是jquery的項(xiàng)目, 所以, 我們要在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/ 官網(wǎng)下載
我寫這個(gè)筆記的時(shí)候, 官網(wǎng)好像下載出錯(cuò)了,我找到了另一種下載的方法
把官網(wǎng)的示例隨便打開(kāi)了個(gè), 找到 上圖中的地址
這樣也可以得到我們想要的 trunjs庫(kù)
上面是安裝, 下面我們開(kāi)始使用
? ? ? <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 ?就是翻頁(yè)組件的容器 --> ? ? ? ? ? ? ? ? ? ? ? </div> ? ? ? ? ? ? ? ? ? ? ? </v-touch> ? ? ? ? ? ? ? ? ? ? ? ?? ?<!-- 這里的 docview1 是用來(lái)存放 pdf轉(zhuǎn)成圖片時(shí),所用到的 canvas 標(biāo)簽的--> ? ? ? ? ? ? ? ? ? ? ? <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轉(zhuǎn)化的圖片地址-用于放大查看所有pdf圖片 */ readPdf(fileUrl,index) { //這個(gè)index 是我代碼中要用的, 如果單獨(dú)使用的話, 可以不要 index 這個(gè)參數(shù) let self = this; let loadingTask1 = PDFJS.getDocument(fileUrl); //讀取pdf文件 console.log(loadingTask1, '-----------loadingTask'); loadingTask1.promise .then(function (pdf) { if (pdf) { // pdf 總頁(yè)數(shù) const pageNum = pdf.numPages; for (let i = 1; i <= pageNum; i++) { // 生成每頁(yè) 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() 方法返回一個(gè)用于在畫(huà)布上繪圖的環(huán)境。 const context = canvas.getContext('2d'); self.openPage(pdf, i, context); } setTimeout(() => { self.exportImg(self,index); }, 2000); } }) .catch(function (reason) { console.error('Error: ' + reason); }); }, //pdf轉(zhuǎn)成canvas /* ** @param loading pdf生成圖片時(shí)的加載狀態(tài) ** @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) //這里根把自已的項(xiàng)目需求,寬高進(jìn)行調(diào)整 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轉(zhuǎn)成圖片(可根據(jù)具體情況,進(jìn)行圖片轉(zhuǎn)化顯示)這里我把所有圖片的base64存放在數(shù)組里面,方便放大查看,也可以直接把生成圖片標(biāo)簽進(jìn)行圖片展示 // 轉(zhuǎn)圖片 exportImg(self,index) { //let canvaslist= document.querySelectorAll('canvas'); let canvaslist = document.getElementsByClassName("h"+index); let pdfPicturePathX = "pdfPicturePath"+index; this[pdfPicturePathX] = []; //這里把所有的圖片地址放入到 pdfPicturePath1 數(shù)組中去 for (let i = 0; i < canvaslist.length; i++) { // let canvas = document.getElementById("pageNum" + (i + 1)); // // 將 canvas 轉(zhuǎn)成 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 轉(zhuǎn)成 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文件轉(zhuǎn)成 base64格式的圖片, 之后把它們存在 pdfPicturePath1的數(shù)組中 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() { // //當(dāng)前頁(yè) // // console.log("Current view: ", $(this).turn("view")); // // //總頁(yè)數(shù) // // 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 } },
下面是我項(xiàng)目的一個(gè)完現(xiàn)代碼
<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="請(qǐng)選擇" 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="請(qǐng)選擇" 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="請(qǐng)選擇" 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:[], //首頁(yè)的分類列表, 一共有六個(gè)分類 //下拉選擇框 三個(gè) selectoptions1:[ ], selectoptions2:[], selectoptions3:[], //下拉選擇框的值 三個(gè) value1:{}, value2:{}, value3:{}, //下拉選擇后的列表 三個(gè) selectList1:[], //列表中選中的標(biāo)記, 主要是為了顯示 條目中的小箭頭 selectItemIndex1:-1, selectList2:[], selectItemIndex2:-2, selectList3:[], selectItemIndex3:-3, //標(biāo)記pdf記號(hào) ispdf1:false, ispdf2:false, ispdf3:false, //showpdf div的標(biāo)記 showpdf1:false, showpdf2:false, showpdf3:false, showfengmian1:true, showfengmian2:true, showfengmian3:true, articleDetail1:{}, articleDetail2:{}, articleDetail3:{}, pdfPicturePath1: [], // pdf轉(zhuǎn)化的圖片地址 pdfPicturePath2: [], // pdf轉(zhuǎn)化的圖片地址 pdfPicturePath3: [], // pdf轉(zhuǎn)化的圖片地址 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(){ //得到首頁(yè)的圖片列表 M.getCategorys().then(res=>{ this.categoryslist = res.data.categories; }) }, //封面被點(diǎn)擊 fengmianclick(index,categoryslistindex){ console.log(index,categoryslistindex); //index 表示是哪一列中的(本屏一共有三列) //categoryslistindex 被點(diǎn)擊的在 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]; //這里要顯示默認(rèn)的項(xiàng)的信息 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); }) }, //通過(guò)文章id來(lái)顯示文章的詳情 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; //當(dāng) showpdfX == true是 一定是顯示了pdf 的滑動(dòng)頁(yè) if(this[showpdfX]){ this[showpdfX] = !this[showpdfX] }else{ //如果是showpdfX 是 false ,那就應(yīng)該是退回上一級(jí)的頁(yè)面 let showfengmianX = "showfengmian"+index; this[showfengmianX] = true; } }, pdfshowClick(index,files){ //index 表示是哪一列中的(本屏一共有三列) let showpdfX = "showpdf"+index; this[showpdfX] = true; //是在這里加載pdf ,還是在列表中點(diǎn)擊的時(shí)候加載pdf 可以測(cè)試一下哪個(gè)要好一點(diǎn) //this.readPdf("bbb.pdf",index) }, chooselist(index,listindex,item){ //第一個(gè)index 表示是哪一列中的(本屏一共有三列) //listindex 表示點(diǎn)擊的是哪一條數(shù)據(jù) let selectItemIndexX = "selectItemIndex"+index; this[selectItemIndexX] = listindex; let selectListX = "selectList"+index; //從selectListX中的數(shù)組中得到這條信息的具體內(nèi)容,并標(biāo)記是否是一個(gè)pdf文件 //看后臺(tái)的設(shè)計(jì),這里可能是要請(qǐng)求接口的 let ispdfX = "ispdf"+index; this[ispdfX] = this[selectListX][listindex].type == "pdf"?true:false this.getArticleDetail(item,index) }, //書(shū)翻頁(yè) changeindexleft(index){ this.$nextTick(()=>{ if(index == 1){ $("#magazine1").turn("next") }else if(index == 2){ $("#magazine2").turn("next") }else if(index == 3){ $("#magazine3").turn("next") } }) }, changeindexright(index){ this.$nextTick(()=>{ if(index == 1){ $("#magazine1").turn("previous") }else if(index == 2){ $("#magazine2").turn("previous") }else if(index == 3){ $("#magazine3").turn("previous") } }) }, //初始化pdf插件 /* ** @param fileUrl pdf有效的查看地址 ** (1、線上地址(如:http://www.xxx.com) ** 2、本地public地址(例如:/static/view.pdf)) ** @param pdfPicturePath1 pdf轉(zhuǎn)化的圖片地址-用于放大查看所有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 總頁(yè)數(shù) const pageNum = pdf.numPages; for (let i = 1; i <= pageNum; i++) { // 生成每頁(yè) 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() 方法返回一個(gè)用于在畫(huà)布上繪圖的環(huán)境。 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 總頁(yè)數(shù) const pageNum = pdf.numPages; for (let i = 1; i <= pageNum; i++) { // 生成每頁(yè) 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() 方法返回一個(gè)用于在畫(huà)布上繪圖的環(huán)境。 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 總頁(yè)數(shù) const pageNum = pdf.numPages; for (let i = 1; i <= pageNum; i++) { // 生成每頁(yè) 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() 方法返回一個(gè)用于在畫(huà)布上繪圖的環(huán)境。 const context = canvas.getContext('2d'); self.openPage(pdf, i, context); } setTimeout(() => { self.exportImg(self,index); }, 2000); } }) .catch(function (reason) { console.error('Error: ' + reason); }); } }, //pdf轉(zhuǎn)成canvas /* ** @param loading pdf生成圖片時(shí)的加載狀態(tài) ** @param scale 控制 canvas顯示的大小 ** @param pdfPicturePath1 pdf轉(zhuǎn)化的圖片地址-用于放大查看所有pdf圖片 */ openPage(pdfFile, pageNumber, context) { let that = this; pdfFile.getPage(pageNumber).then(function (page) { // reference canvas via context let viewport = page.getViewport({scale:1}); let scale =(847 / viewport.height).toFixed(2) let viewport1 = page.getViewport({scale:scale}); let canvas = context.canvas; canvas.width = viewport1.width; canvas.height = viewport1.height; canvas.style.width = '100%'; canvas.style.height = '100%'; let renderContext = { canvasContext: context, viewport: viewport1 }; page.render(renderContext); that.loading = false; }); return; }, //canvas轉(zhuǎn)成圖片(可根據(jù)具體情況,進(jìn)行圖片轉(zhuǎn)化顯示)這里我把所有圖片的base64存放在數(shù)組里面,方便放大查看,也可以直接把生成圖片標(biāo)簽進(jìn)行圖片展示 // 轉(zhuǎn)圖片 exportImg(self,index) { //let canvaslist= document.querySelectorAll('canvas'); let canvaslist = document.getElementsByClassName("h"+index); let pdfPicturePathX = "pdfPicturePath"+index; this[pdfPicturePathX] = []; //這里把所有的圖片地址放入到 pdfPicturePath1 數(shù)組中去 for (let i = 0; i < canvaslist.length; i++) { // let canvas = document.getElementById("pageNum" + (i + 1)); // // 將 canvas 轉(zhuǎn)成 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 轉(zhuǎn)成 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() { // //當(dāng)前頁(yè) // // console.log("Current view: ", $(this).turn("view")); // // //總頁(yè)數(shù) // // 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() { //當(dāng)前頁(yè) // console.log("Current view: ", $(this).turn("view")); // //總頁(yè)數(shù) // 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() { //當(dāng)前頁(yè) // console.log("Current view: ", $(this).turn("view")); // //總頁(yè)數(shù) // 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>
說(shuō)一下這個(gè)項(xiàng)目, 這個(gè)項(xiàng)目中使用 turnjs 的時(shí)候
只能 倒翻書(shū), 不能正翻書(shū), direction:“rtl”, 只能rtl才生效, 如果是 ltr 就是出錯(cuò),無(wú)效果
后來(lái)找到了另外一個(gè)解決辦法 v-touch 就是解決的辦法
首先 禁止掉 turnjs 的翻頁(yè)效果
//這段代碼就是禁止 turnjs 的翻書(shū)效果 $("#magazine1").bind("start",function(e,p,c){ if(c == "tl"||c == 'tr'){ e.preventDefault(); } })
然后, 使用 v-touch 監(jiān)聽(tīng) 左右滑動(dòng)
//書(shū)翻頁(yè) changeindexleft(index){ this.$nextTick(()=>{ if(index == 1){ $("#magazine1").turn("next") } }) }, changeindexright(index){ this.$nextTick(()=>{ if(index == 1){ $("#magazine1").turn("previous") } }) },
這樣書(shū)就可以 前后翻動(dòng)了 解決了 turnjs 只能 倒翻書(shū)的問(wèn)題
還有一個(gè)問(wèn)題, 就是 因?yàn)?,本?yè)面會(huì)加載不同的pdf 文件, 而 turnjs 初始化后 $(“#magazine1”).turn();會(huì)在 其中添加很多其它的標(biāo)記, 如果在 $(“#margazine1”).turn()初始化完成之后 , 再執(zhí)行一次 $(“#margazine1”).turn();就會(huì)形成無(wú)限的嵌套,導(dǎo)至顯示出錯(cuò)。
最初我使用的是 vue 的數(shù)據(jù)改變來(lái) 更改 pdf 圖片的顯示, 就踩了上面的坑, 后來(lái)經(jīng)過(guò)分析, 我在代碼中使用了 jquery 的方法來(lái)改變數(shù)據(jù)
上面的代碼中
以上便是我使用 vue pdf-dist 和turnjs做翻頁(yè)的心得
到此這篇關(guān)于vue中使用pdfjs-dist + turnjs實(shí)現(xiàn)頁(yè)面的翻書(shū)瀏覽的文章就介紹到這了,更多相關(guān)vue頁(yè)面的翻書(shū)瀏覽內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
koa2+vue實(shí)現(xiàn)登陸及登錄狀態(tài)判斷
這篇文章主要介紹了koa2+vue實(shí)現(xiàn)登陸及登錄狀態(tài)判斷,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2019-08-08Vue中使用Openlayer實(shí)現(xiàn)加載動(dòng)畫(huà)效果
這篇文章主要介紹了Vue+Openlayer加載動(dòng)畫(huà)效果的實(shí)現(xiàn)代碼,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-08-08Vue?3?使用moment設(shè)置顯示時(shí)間格式的問(wèn)題及解決方法
在Vue?3中,因?yàn)檫^(guò)濾器(filter)已經(jīng)被廢棄,取而代之的是全局方法(global?method),本文給大家介紹Vue?3?使用moment設(shè)置顯示時(shí)間格式的問(wèn)題及解決方法,感興趣的朋友一起看看吧2023-12-12Vue3 Ref獲取真實(shí)DOM學(xué)習(xí)實(shí)戰(zhàn)
這篇文章主要為大家介紹了Vue3 Ref獲取真實(shí)DOM學(xué)習(xí)實(shí)戰(zhàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06vue之保留小數(shù)點(diǎn)兩位小數(shù) 使用filters(過(guò)濾器)
這篇文章主要介紹了vue之保留小數(shù)點(diǎn)兩位小數(shù) 使用filters(過(guò)濾器),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11vue element中axios下載文件(后端Python)
這篇文章主要介紹了vue element中axios下載文件(后端Python)的實(shí)例代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2019-05-05