Vue借助turn.js实现翻书效果预览pdf文件
1. 安装 turn.js
需要jQuery
2. 安装 pdf.js
npm install vue-pdf --save-dev
3. 主体代码
<template>
<div id="flipbook" ref="flipbook" v-loading="pdfLoading" v-show="rendered">
<div v-for="item in pageNum" :key="item">
<div class="gradient"></div>
<canvas :id="`pdf-canvas-${item}`" class="pdf-page" />
</div>
</div>
</template>
<script>
import $ from "jquery";
import turn from "../../assets/js/turn.min.js";
import * as pdfjs from "pdfjs-dist";
import * as pdfjsWorker from "pdfjs-dist/build/pdf.worker.entry";
pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;
// console.log(pdfjs);
export default {
name: "PdfTurnViewer",
props: {
pdfUrl: {
type: String,
default: "",
},
},
data() {
return {
pdfLoading: false,
rendered: false,
pageNum: 0,
pdfCtx: null,
pageSize: {
width: 0,
height: 0,
},
};
},
mounted() {
this.getPdf(this.pdfUrl);
// this.startTurn();
},
methods: {
getPdf(url) {
this.pdfLoading = true;
const loadingTask = pdfjs.getDocument(url);
// console.log(loadingTask);
loadingTask.promise
.then((pdf) => {
this.pdfCtx = pdf;
this.pageNum = pdf.numPages;
this.$nextTick(() => {
this.renderPdf();
});
})
.catch((err) => {
this.pdfLoading = false;
console.error("pdf加载失败", err);
});
},
renderPdf(num = 1) {
this.pdfCtx.getPage(num).then((page) => {
const canvas = document.getElementById(`pdf-canvas-${num}`);
const ctx = canvas.getContext("2d");
const viewport = page.getViewport({ scale: 1 });
this.pageSize = {
width: viewport.width,
height: viewport.height,
};
canvas.width = viewport.width;
canvas.height = viewport.height;
const clientWidth = 500;
canvas.style.width = clientWidth + "px";
// // 根据pdf每页的宽高比例设置canvas的高度
// canvas.style.height =
// clientWidth * (viewport.height / viewport.width) + "px";
page.render({
canvasContext: ctx,
viewport,
});
if (num < this.pageNum) {
this.renderPdf(num + 1);
} else {
this.pdfLoading = false;
this.rendered = true;
console.log("render finished!");
this.startTurn();
// loading.clear();
}
});
},
startTurn() {
let self = this;
$("#flipbook").turn("center");
$("#flipbook").turn("page");
// this.$nextTick(() => {
$("#flipbook")
.turn({
display: "double", //single double
elevation: 50,
gradients: true,
duration: 1000,
autoCenter: true,
acceleration: true,
page: 2,
width: 1000,
height: (self.pageSize.height * 1000) / self.pageSize.width / 2,
when: {
turning: (event, page, pageObj) => {
// 禁止第1页时点击翻页
page === 1 && event.preventDefault();
// console.log(self.pageSize);
// console.log("翻页中", page); //246偶数
// if (page === this.numPages - 3) {
// console.log("加载下一页");
// this.numPages++;
// }
},
// turned: (event, page, pageObj) => {
// //当前页
// console.log("当前页: ", page);
// console.log("当前页数组: ", pageObj);
// //总页数
// // console.log("共有" + $("#flipbook").turn("pages") + " 页");
// },
},
})
.bind("start", function (event, pageObject, corner) {
// console.log("hover位置方向", corner);
if (pageObject.page === 2) {
// 禁止第1页时手动拖拽翻页
event.preventDefault();
}
});
// .bind("turning", (event, page, view) => {
// alert("turning the page to" + page);
// });
// .bind("last", function (event, pageObject, corner) {
// console.log("最后一页");
// });
// });
// 销毁
// $("#flipbook").turn("destroy").remove();
},
},
};
</script>
<style scoped>
.container {
width: 100%;
height: 100%;
text-align: center;
}
#flipbook {
height: 800px;
}
#flipbook .even .gradient {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: -webkit-gradient(
linear,
left top,
right top,
color-stop(0.95, rgba(0, 0, 0, 0)),
color-stop(1, rgba(0, 0, 0, 0.2))
);
}
</style>