vue-pdf 单页显示所有,滚动显示实现分页跳转
// 顶部按钮
<div class="my-dialog-title">
<div class="pdf_btn" :style="isFullScreen ? {top: 0 } : ''">
<div style="display: flex; align-items: center; width: 70%">
<!-- 分页 -->
<template style="display: flex;margin-right: 16px;font-size: 14px !important;;font-weight: 400">
<el-button icon="el-icon-arrow-left" @click="prePage">上一页</el-button>
<div class="page-count" style="margin: 0 8px; vertical-align: middle;line-height: 46px;height: 46px; font-size: 14px !important;">
<el-input-number v-model="currentPageNum" :controls="false" :min="1" :max="numPages" style="width: 40px;vertical-align: middle" @change="pageNumChange" />
/ {{ numPages }}</div>
<el-button @click="nextPage">下一页
<i class="el-icon-arrow-right el-icon--right" />
</el-button>
<el-divider direction="vertical" />
</template>
<!-- 缩放 -->
<template style="display: flex;margin-right: 16px;font-weight: 400;font-size: 14px !important;">
<el-button icon="el-icon-zoom-in" @click="changeSize('big')" />
<span style="display: inline-block;margin: 0 8px;font-size: 14px !important;">
{{ styleObj.width + "%" }}
</span>
<el-button icon="el-icon-zoom-out" @click="changeSize('small')" />
</template>
</div>
<div style="display: flex; width: 30%; justify-content: end; align-items: center">
<!-- 最大化 -->
<template style="display: flex;margin-right: 16px">
<el-button
icon="el-icon-full-screen"
@click.native="fullScreenToggle"
/>
<el-divider direction="vertical" />
</template>
<!-- 下载 -->
<el-button
icon="el-icon-download"
type="warning"
plain
@click="downloadPdf"
/>
</div>
</div>
</div>
// pdf 页面显示
<div class="my-dialog-content-box" style="position: relative">
<div class="all-box" :style="{height: isFullScreen ? '100vh' : ''}" @scroll="scrollEvent($event)">
<div v-for="i in numPages" :key="i" class="pdf-item" :style="{'width': styleObj.width + '%'}">
<pdf
ref="pdf"
class="pdf-item"
:src="pdfSrc"
:page="i"
/>
</div>
</div>
</div>
js
<script>
import pdf from "vue-pdf";
export default {
components: { pdf },
data() {
return {
remindShow: "加载文件中,文件较大请耐心等待...",
url: process.env.VUE_APP_PROXY + "/file/downloadfile/", // 下载调用的接口地址
pdfSrc: "",
pageNum: 1,
pageTotalNum: 1, // 总页数
pdfShow: false, // pdf 显示刷新
rotate: 0,
sizeMultiple: 10,
isFullScreen: false, // 全屏
deviceListIsFinish: false, // 是否加载完成
deviceListIsLoad: false, // 是否加载更多
deviceTip: "",
numPages: null,
currentPageNum: 1,
pdfItemHeight: 0, // 单页高度
cutHeight: 0, // 切换高度
// 加载进度
loadedRatio: 0,
styleObj: {
width: 100
}
};
},
async mounted() {
const _dom = document.querySelector("body");
// 将当前组件挂载到body下的最后
_dom.insertBefore(this.$el, _dom.lastChild);
this.getNumPages();
window.addEventListener("resize", this.resize);
},
methods: {
// 滚动
scrollEvent(e) {
if (e instanceof Event) {
const el = e.target;
const scrollTop = el.scrollTop;
if (scrollTop > 0) {
this.currentPageNum = Math.ceil((scrollTop + this.cutHeight) / this.pdfItemHeight);
}
}
},
// 跳转页面
pageNumChange(e) {
const pdfBox = document.getElementsByClassName("all-box")[0];
if (e !== 1) {
window.setTimeout(() => {
pdfBox.scrollTop = this.pdfItemHeight * (this.currentPageNum - 1);
}, 100);
} else {
window.setTimeout(() => {
pdfBox.scrollTop = 1;
}, 100);
}
},
// 上一页
prePage() {
const pdfBox = document.getElementsByClassName("all-box")[0];
if (this.currentPageNum > 1) {
window.setTimeout(() => {
pdfBox.scrollTop = this.pdfItemHeight * (this.currentPageNum - 1);
}, 100);
this.currentPageNum = this.currentPageNum - 1;
} else {
window.setTimeout(() => {
pdfBox.scrollTop = this.pdfItemHeight * (this.numPages - 1);
}, 100);
this.currentPageNum = this.numPages;
}
},
// 下一页
nextPage() {
const pdfBox = document.getElementsByClassName("all-box")[0];
if (this.currentPageNum < this.numPages) {
window.setTimeout(() => {
pdfBox.scrollTop = this.pdfItemHeight * this.currentPageNum;
this.currentPageNum = this.currentPageNum + 1;
}, 100);
} else {
window.setTimeout(() => {
pdfBox.scrollTop = 1;
}, 100);
this.currentPageNum = 1;
}
},
resize() {
if (!this._checkFull()) {
this.isFullScreen = false;
setTimeout(() => {
this.cutHeight = (document.documentElement.clientHeight * 0.85 - 65) * 0.5;
this.pdfItemHeight = document.getElementsByClassName("pdf-item")[0].offsetHeight + 30;
const pdfBox = document.getElementsByClassName("all-box")[0];
this.currentPageNum = Math.ceil((pdfBox.scrollTop + this.cutHeight) / this.pdfItemHeight);
}, 200);
}
},
// 变更pdf 大小
changeSize(type) {
if (type === "big") {
if (this.sizeMultiple < 10) {
this.sizeMultiple = this.sizeMultiple + 1;
}
} else {
if (this.sizeMultiple > 5) {
this.sizeMultiple = this.sizeMultiple - 1;
}
}
this.styleObj.width = this.sizeMultiple * 10;
setTimeout(() => {
this.cutHeight = (document.documentElement.clientHeight * 0.85 - 65) * 0.5;
this.pdfItemHeight = document.getElementsByClassName("pdf-item")[0].offsetHeight + 30;
const pdfBox = document.getElementsByClassName("all-box")[0];
this.currentPageNum = Math.ceil((pdfBox.scrollTop + this.cutHeight) / this.pdfItemHeight);
}, 200);
},
getNumPages() {
this.pdfSrc = pdf.createLoadingTask({ url: this.pdfUrl, CMapReaderFactory }, {
// 进度条
onProgress: (status) => {
this.loadedRatio = (status.loaded / status.total) >= 1 ? 1 : status.loaded / status.total;
}
});
this.$nextTick(() => {
this.pdfShow = true;
});
this.pdfSrc.promise.then((pdf) => {
console.log(pdf);
this.numPages = pdf._pdfInfo.numPages;
this.pageTotalNum = pdf._pdfInfo.numPages;
this.pdfShow = true;
}).catch((err) => {
console.error("pdf 加载失败", err);
}).finally(() => {
setTimeout(() => {
this.cutHeight = (document.documentElement.clientHeight * 0.85 - 65) * 0.5;
this.pdfItemHeight = document.getElementsByClassName("pdf-item")[0].offsetHeight + 30;
}, 500);
});
},
// 全屏
fullScreenToggle() {
const $pdf = this.$el;
if (this._checkFull()) {
const eventOut =
document.cancelFullScreen ||
document.webkitCancelFullScreen ||
document.mozCancelFullScreen ||
document.msExitFullScreen;
if (typeof eventOut !== "undefined" && eventOut) {
eventOut.call(document);
}
this.isFullScreen = false;
} else {
if ($pdf.requestFullscreen) {
$pdf.requestFullscreen();
} else if ($pdf.webkitRequestFullscreen) {
$pdf.webkitRequestFullscreen();
} else if ($pdf.mozRequestFullscreen) {
$pdf.mozRequestFullscreen();
} else if ($pdf.msRequestFullscreen()) {
$pdf.msRequestFullscreen();
} else {
this.$message.warning("该浏览器不支持全屏!");
this.isFullScreen = false;
return;
}
this.isFullScreen = true;
setTimeout(() => {
this.cutHeight = (document.documentElement.clientHeight - 65) * 0.5;
this.pdfItemHeight = document.getElementsByClassName("pdf-item")[0].offsetHeight + 30;
const pdfBox = document.getElementsByClassName("all-box")[0];
this.currentPageNum = Math.ceil((pdfBox.scrollTop + this.cutHeight) / this.pdfItemHeight);
}, 200);
}
},
// 检查是否为全屏状态
_checkFull() {
let isFull =
document.fullscreenElement ||
document.mozFullScreenElement ||
document.webkitFullscreenElement ||
document.msFullscreenElement;
if (isFull === undefined) isFull = false;
return isFull;
},
}
}
</script>
<style scoped lang="less">
/deep/ .el-input__inner{
font-size: 14px;
}
.progress {
position: absolute;
right: 50%;
top: 50%;
text-align: center;
}
.progress > span {
color: #199edb;
font-size: 14px;
}
.my-dialog{
width: 100vw;
height: 100vh;
overflow-y: scroll;
background-color: rgba(0,0,0,0.6);
top: 0;
left: 0;
position: fixed;
z-index: 3003 !important;
.is-full-screen{
top: 0 !important;
left: 0 !important;
height: 100vh !important;
width: 100% !important;
/deep/ .my-dialog-content-box{
height: calc(100vh - 100px) !important;
max-height: 100vh !important;
}
}
.my-dialog-box{
width: 500px;
min-height: 300px;
position: absolute;
top: 5%;
left: 30%;
background: #FFFFFF;
box-shadow: 0 8px 20px 0 rgba(215,221,228,0.5);
border-radius: 8px;
.my-dialog-title{
width: 100%;
height: 62px;
line-height: 62px;
box-shadow: 0 8px 20px 0 rgba(215,221,228,0.5);
border-radius: 8px 8px 0 0;
padding: 0 32px;
position: relative;
//overflow: hidden;
box-sizing: border-box;
.bottom-img{
height: 5px;
position: absolute;
bottom: 0;
left: 32px;
line-height: 5px;
img{
height: 5px;
}
}
.my-dialog-title-text{
display: inline-block;
height: 26px;
font-size: 18px;
font-weight: 600;
color: #2D313D;
line-height: 26px;
}
.my-dialog-title-remark{
display: inline-block;
height: 20px;
font-size: 12px;
font-weight: 400;
color: #757A8A;
line-height: 20px;
margin-left: 8px;
}
.close-icon{
display: inline-block;
float: right;
font-size: 14px;
}
}
.my-dialog-content-box{
max-height: calc(85vh - 65px);
padding: 0 48px 32px 48px;
overflow-y: auto;
margin-top: 16px;
position: relative;
}
.my-dialog-content-box::-webkit-scrollbar{
display: none;
}
}
}
.pdf-item{
margin: 0 auto 30px;
overflow: hidden;
}
.pdf-box{
margin-top: 60px;
width: 100%;
display: flex;
justify-content: center;
}
/deep/ .my-dialog-content-box{
padding: 0 40px !important;
background: #d4d4d7;
//background: #323639;
position: relative;
}
.all-box{
margin-top: 38px;
width: 100%;
height: calc(85vh - 100px);
overflow-y: auto;
}
.all-box::-webkit-scrollbar{
display: none;
}
.pdf_btn{
height: 46px;
line-height: 46px;
width: 100%;
position: absolute;
top: 63px;
left: 0;
background-color: #fff;
z-index: 3000;
border-top: 1px solid #dcdee2;
box-shadow: 0 1px 3px #e8eaec;
padding: 0 20px;
display: flex;
justify-content: space-between
}
.custom-button {
width: 90px;
height: 46px;
line-height: 46px;
font-size: 14px;
display: flex;
padding: 0;
justify-content: center;
margin: 0 16px;
}
</style>