基于vue-pdf的PDF预览,缩放、旋转、拖拽、下一页
vue-pdf
vue.js pdf viewer
项目地址:https://gitcode.com/gh_mirrors/vu/vue-pdf
免费下载资源
·
先说一下利用iframe打开pdf效果如下
代码如下这种感觉更简单,打印各方面都可以
<el-dialog
v-if="showPdf"
:visible.sync="showPdf"
width="800px"
@close="showPdf=false"
title="PDF预览"
>
<div class="pdf">
<iframe :src="pdfHref" frameborder="0" style="width: 100%; height: 600px;">
</iframe>
</div>
</el-dialog>
下面说一下基于vue-pdf的二次开发
效果图如下:因为上一页下一页没有icon,所以用的旋转的icon
1、安装vue-pdf
npm install --save vue-pdf
2、具体引用使用
<template>
<div :class="{ dialog:true, active:show}" @mousewheel="mousewheelFn">
<a v-if="showClose" class="close" @click="closeFn"></a>
<div
class="wrap"
ref="wrap"
>
<div
class="pdfWrap"
id="pdfWrap"
:style="{cursor: 'pointer', transform: `rotate(${rotate}deg)`,width: `${scale}%`}"
>
<pdf
v-if="pdfSrc"
:src="pdfSrc"
:page="currentPage"
ref="pdf"
@num-pages="pageCount=$event"
@page-loaded="currentPage=$event"
@loaded="loadPdfHandler"
></pdf>
</div>
<div class="control">
<a
v-for="(item,index) in ['放大(+)','缩小(-)','原图(1:1)','向左旋转90°','向右旋转90°','上一页','下一页']"
:key="index"
@click="handle(index)"
:title="item"
></a>
</div>
<div :class="{toast:true,showToast,animate}">{{toastScale}}</div>
</div>
</div>
</template>
<script>
import { bind, unbind, objDrag } from "js/js";
import pdf from "vue-pdf";
export default {
data() {
return {
initPosX: 0,
initPosY: 0,
pdfSrc: "",
currentPage: 0, // pdf文件页码
pageCount: 0, // pdf文件总页数
numPages: 1,
activeIndex: 0,
iWidth: document.documentElement.clientWidth,
iHeight: document.documentElement.clientHeight,
scale: 50,
rotate: 0,
scaleAdd: 10,
rotateAdd: 90,
showToast: false,
animate: false,
toastTimer1: null,
toastTimer2: null,
objDrag: null
};
},
computed: {
toastScale() {
let { scale } = this;
return `${scale}%`;
}
},
props: {
parent: {
//父组件的this
type: Object,
default: null,
required: true
},
show: {
//是否显示组件
type: Boolean,
default: false
},
showName: {
//控制显示组件的名称
type: String,
default: ""
},
showClose: {
//是否显示组件关闭按钮
type: Boolean,
default: true
},
dochref: {
//pdfurl
type: String,
default: ""
}
},
components: {
pdf
},
beforeDestroy() {
unbind(window, "resize", this.initPos);
},
mounted() {
//图片加上拖拽
bind(window, "resize", this.initPos);
this.pdfSrc = this.dochref;
},
methods: {
initPos() {
let pdfWrap = document.getElementById("pdfWrap");
this.iWidth = document.documentElement.clientWidth;
this.iHeight = document.documentElement.clientHeight;
let width = pdfWrap.clientWidth;
let height = pdfWrap.clientHeight;
this.initPosX = this.iWidth / 4;
this.initPosY = this.iHeight / 8;
this.scale = 50;
this.rotate = 0;
pdfWrap.style.left = this.initPosX + "px";
pdfWrap.style.top = this.initPosY + "px";
},
changePdfPage(val) {
if (val === 0 && this.currentPage > 1) {
this.currentPage--;
}
if (val === 1 && this.currentPage < this.pageCount) {
this.currentPage++;
}
},
loadPdfHandler(e) {
this.currentPage = 1; // 加载的时候先加载第一页
this.drag("pdfWrap");
this.initPos();
},
closeFn() {
let { parent, showName } = this;
if (parent && showName && parent[showName]) {
parent[showName] = false;
this.scale = 50;
this.rotate = 0;
}
},
showToastFn() {
this.showToast = true;
this.animate = false;
clearTimeout(this.toastTimer1);
clearTimeout(this.toastTimer2);
this.toastTimer1 = setTimeout(() => {
this.animate = true;
this.toastTimer2 = setTimeout(() => {
this.showToast = false;
this.animate = false;
}, 300);
}, 300);
},
magnify() {
let { scale } = this;
scale += this.scaleAdd;
scale = scale > 1000 ? 1000 : scale;
this.showToastFn();
this.scale = scale;
},
shrink() {
let { scale } = this;
scale -= this.scaleAdd;
scale = scale < 10 ? 10 : scale;
this.showToastFn();
this.scale = scale;
},
handle(index) {
let { scale, rotate } = this;
switch (index) {
case 0:
this.magnify();
break;
case 1:
this.shrink();
break;
case 2:
this.initPos();
break;
case 3:
this.rotate -= this.rotateAdd;
break;
case 4:
this.rotate += this.rotateAdd;
break;
case 5:
this.changePdfPage(0);
break;
case 6:
this.changePdfPage(1);
break;
}
},
mousewheelFn(ev) {
let up = true;
if (ev.wheelDelta) {
up = ev.wheelDelta > 0 ? true : false;
} else {
up = ev.detail < 0 ? true : false;
}
if (up) {
this.magnify();
} else {
this.shrink();
}
},
drag(obj) {
this.objDrag = new objDrag(obj);
}
}
};
</script>
<style lang="scss" scoped>
@import "~css/public.scss";
@mixin close() {
width: 50px;
height: 50px;
background: rgba(255, 255, 255, 0.9)
url("../../images/imgControl/icon_close.png") no-repeat center center;
background-size: 16px;
position: absolute;
right: 0;
top: 0;
z-index: 10;
cursor: pointer;
}
.dialog {
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.6);
position: fixed;
left: 0;
top: 0;
z-index: 1999;
display: none;
&.active {
display: block;
}
> .close {
@include close;
right: 30px;
top: 30px;
}
> .wrap {
width: 100%;
height: 100%;
position: relative;
.pdfWrap {
position: absolute;
}
> .control {
display: flex;
justify-content: center;
align-items: center;
width: 300px;
padding: 5px 0;
height: 30px;
background-color: rgba(255, 255, 255, 0.9);
border-radius: 25px;
position: absolute;
left: 50%;
margin-left: -150px;
bottom: 10px;
a {
width: 20px;
margin: 0 5px;
height: 20px;
background: no-repeat center center;
background-size: 16px;
&:nth-of-type(1) {
background-image: url("../../images/imgControl/icon_enlarge_zxzx.png");
}
&:nth-of-type(2) {
background-image: url("../../images/imgControl/icon_narrow_zxzx.png");
}
&:nth-of-type(3) {
background-image: url("../../images/imgControl/icon_ybl_zxzx.png");
}
&:nth-of-type(4) {
background-image: url("../../images/imgControl/icon_turn_zxzx.png");
}
&:nth-of-type(5) {
background-image: url("../../images/imgControl/icon_turn2_zxzx.png");
}
&:nth-of-type(6) {
background-image: url("../../images/imgControl/icon_turn_zxzx.png");
}
&:nth-of-type(7) {
background-image: url("../../images/imgControl/icon_turn2_zxzx.png");
}
&:hover {
background-color: $main;
&:nth-of-type(1) {
background-image: url("../../images/imgControl/icon_enlarge2_zxzx.png");
}
&:nth-of-type(2) {
background-image: url("../../images/imgControl/icon_narrow2_zxzx.png");
}
&:nth-of-type(3) {
background-image: url("../../images/imgControl/icon_ybl2_zxzx.png");
}
&:nth-of-type(4) {
background-image: url("../../images/imgControl/icon_turn3_zxzx.png");
}
&:nth-of-type(5) {
background-image: url("../../images/imgControl/icon_turn4_zxzx.png");
}
&:nth-of-type(6) {
background-image: url("../../images/imgControl/icon_turn3_zxzx.png");
}
&:nth-of-type(7) {
background-image: url("../../images/imgControl/icon_turn4_zxzx.png");
}
}
}
}
> .toast {
width: 100px;
height: 30px;
line-height: 30px;
text-align: center;
background-color: rgba(255, 255, 255, 0.9);
border-radius: 15px;
position: absolute;
top: 30px;
left: 50%;
margin-left: -50px;
z-index: 10;
transition: opacity 0.3s ease-out;
opacity: 1;
display: none;
&.showToast {
display: block;
}
&.animate {
opacity: 0;
}
}
}
}
</style>
bind,unbind,objDrag (这三个函数你也可以自己封装)
//绑定事件,可重复绑定('事件名称'必须加引号)
function bind(obj, evname, fn) {
if (obj.addEventListener) {
obj.addEventListener(evname, fn, false);
if (evname == 'mousewheel') {
obj.addEventListener('DOMMouseScroll', fn, false);
}
} else {
obj.attachEvent('on' + evname, function () {
fn.call(obj);
});
}
};
//取消绑定,可重复取消('事件名称'必须加引号)
function unbind(obj, evname, fn) {
if (obj.removeEventListener) {
obj.removeEventListener(evname, fn, false);
if (evname == 'mousewheel') {
obj.removeEventListener('DOMMouseScroll', fn, false);
}
} else {
obj.detachEvent('on' + evname, fn);
}
};
// 拖拽
function objDrag(id) {
var _this = this;
this.oDiv = document.getElementById(id);
this.oDiv.onmousedown = function (event) {
_this.fnDown(event);
return false;
}
this.positionArray = []
this.nX = null;
this.nY = null;
this.timer = null;
}
objDrag.prototype.fnDown = function (event) {
var _this = this;
var evt = event || window.event;
this.nX = evt.clientX - this.oDiv.offsetLeft;
this.nY = evt.clientY - this.oDiv.offsetTop;
document.onmousemove = function (event) {
_this.fnMove(event);
}
this.oDiv.onmouseup = function (event) {
_this.fnUp(event)
};
}
objDrag.prototype.fnMove = function (event) {
var evt = event || window.event;
var left = evt.clientX - this.nX;
var top = evt.clientY - this.nY;
this.oDiv.style.left = left + 'px';
this.oDiv.style.top = top + 'px';
this.positionArray.push({
left: this.oDiv.offsetLeft,
top: this.oDiv.offsetTop
});
}
objDrag.prototype.returnWay = function () { // 拖拽轨迹原路返回
console.log(this.positionArray.length);
let positionArray = this.positionArray
this.positionArray = []
let _this = this
console.log(positionArray, 'pos')
var index = positionArray.length - 1;
this.timer = setInterval(function () {
if (index < 0) {
clearInterval(this.timer);
return;
}
if (positionArray.length) {
console.log(_this.oDiv, '_this.oDiv')
if (_this.oDiv.style) {
_this.oDiv.style.left = positionArray[index--].left + "px";
_this.oDiv.style.top = positionArray[index--].top + "px";
}
}
}, 1);
}
objDrag.prototype.fnUp = function () {
document.onmousemove = null;
}
使用方式
<pdfDialog
v-if="showPdf"
:parent="this"
:show="showPdf"
:showName="'showPdf'"
:control="true"
:dochref="pdfHref"
>
</pdfDialog>
GitHub 加速计划 / vu / vue-pdf
2.19 K
520
下载
vue.js pdf viewer
最近提交(Master分支:2 个月前 )
a9f01b23 - 7 个月前
c188a043
add open_collective vue-pdf 8 个月前
更多推荐
已为社区贡献2条内容
所有评论(0)