写一个图片预览的组件
<template>
<div class="wrapper" :style="{height:wrapperHeight}">
<div class="imgName">
<span class="left"> {{imgIndex}} / {{imgData.length}}</span>
<span class="center" v-if="viewTitle">{{viewTitle}} ~ {{imgIndex}}</span>
<span class="center" v-else>{{imgIndex}}</span>
</div>
<div class="content">
<div class="left-content">
<div class="imgContainer" ref="imgContainer">
<img :src="'api/uploadsfile/' +bigImgUrl" ref="bigImg" alt="" class="bigImg">
<transition name="fade">
<span v-show="showTips" class="tips">{{tipsText}}</span>
</transition>
</div>
</div>
<!-- 缩略图容器 -->
<div class="thumbnailContainer" v-if="displayThumbnailContainer">
<div class="view">
<span @click="handlePrevmin" style="position:absolute;top:-5px;">
<i class="el-icon-caret-top" style="font-size:30px;color:#fff;"></i>
</span>
<ul ref="slip">
<li v-for="(item, index) in this.imgData" @click="switchImgUrl(index)" :key="index">
<img :src="'api/uploadsfile/' +item.url" alt="" :class="checkId==index?'checkImg':''">
</li>
</ul>
<span @click="handleNextmin" style="position:absolute;bottom:-11px;">
<i class="el-icon-caret-bottom" style="font-size:30px;color:#fff;"></i>
</span>
</div>
</div>
</div>
<!-- 操作按钮 -->
<div class="handleContainer cancelselect" onselectstart="return false">
<ul>
<li @click="handlePrev">
<i class="el-icon-caret-left"></i>
</li>
<li @click="handleNext">
<i class="el-icon-caret-right"></i>
</li>
<li @click="reduce">
<i class="el-icon-zoom-out"></i>
</li>
<li @click="enlarge">
<i class="el-icon-zoom-in"></i>
</li>
<li @click="rotate">
<i class="el-icon-refresh"></i>
</li>
<li @click="downloadImg((bigImgUrl), bigImgName)">
<i class="el-icon-download"></i>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
name: "vue-picture-viewer",
props: {
imgData: {
type: Array,
default: []
},
viewTitle: {
type: String,
default:''
},
switch: {
type: Boolean,
default: true
},
propsId:{
type: [String,Number],
default:''
}
},
watch: {
imgData: {
handler(newVal, oldVal) {
this.bigImgUrl = this.imgData[0].url;
this.bigImgName = this.imgData[0].name;
this.imgLength = this.imgData.length;
this.imgIndex = 1;
this.checkId=0;
this.i = 0;
this.p = 0;
this.$refs.slip.style.marginTop = 0
},
deep: true
},
viewTitle:{
handler(newVal, oldVal) {
this.imgIndex = 1;
this.i = 0;
this.p = 0;
},
deep: true
},
propsId:{
handler(newVal, oldVal) {
this.changePropsId()
},
deep: true
},
},
created () {
if(this.propsId){
this.bigImgUrl = this.imgData[this.propsId].url;
this.bigImgName = this.imgData[this.propsId].name;
this.imgLength = this.imgData.length;
this.i = this.propsId;
this.p = this.propsId;
this.imgIndex =this.propsId+1;
this.checkId=this.propsId;
}
},
data() {
return {
wrapperHeight: document.body.clientHeight - 70 + "px",
displayThumbnailContainer: this.switch,
// 图片容器数据
i: 0,
p: 0,
checkId:0,
rotateDeg: 0,
bigImgUrl: this.imgData[0].url,
bigImgName: this.imgData[0].name,
imgLength: this.imgData.length,
imgIndex: 1,
showTips: false,
tipsText: "",
bigImgConWidth: "",
bigImgConHeight: ""
};
},
methods: {
changePropsId(){
this.bigImgUrl = this.imgData[this.propsId].url;
this.bigImgName = this.imgData[this.propsId].name;
this.imgLength = this.imgData.length;
this.i = this.propsId;
this.p = this.propsId;
this.imgIndex =this.propsId+1;
this.checkId=this.propsId;
},
// 放大
enlarge() {
this.$nextTick(function() {
this.$refs.bigImg.style.width =
this.$refs.bigImg.offsetWidth * 1.3 + "px";
this.$refs.bigImg.style.height =
this.$refs.bigImg.offsetHeight * 1.3 + "px";
});
},
// 缩小
reduce() {
this.$refs.bigImg.style.width =
this.$refs.bigImg.offsetWidth * 0.7 + "px";
this.$refs.bigImg.style.height =
this.$refs.bigImg.offsetHeight * 0.7 + "px";
},
// 旋转
rotate() {
if (this.rotateDeg === 0) {
this.$refs.bigImg.style.transform = "rotate(90deg)";
this.rotateDeg++;
} else if (this.rotateDeg === 1) {
this.$refs.bigImg.style.transform = "rotate(180deg)";
this.rotateDeg++;
} else if (this.rotateDeg === 2) {
this.$refs.bigImg.style.transform = "rotate(270deg)";
this.rotateDeg++;
} else if (this.rotateDeg === 3) {
this.$refs.bigImg.style.transform = "rotate(360deg)";
this.rotateDeg = 0;
}
},
// 点击缩略图切换图片
switchImgUrl(num) {
this.checkId =num
let _this = this;
this.bigImgUrl = this.imgData[num].url;
this.imgIndex = num + 1;
this.bigImgName = this.imgData[num].name;
this.i=this.checkId
this.p=this.checkId
},
// 切换到上一张
handlePrev() {
let _this = this;
this.i--;
this.$refs.bigImg.style.transform = "rotate(0deg)";
this.rotateDeg = 0;
if (this.i === -1) {
_this.tips("已经是第一张了!");
this.i = 0;
} else {
this.bigImgUrl = this.imgData[this.i].url;
this.imgIndex = this.i + 1;
this.bigImgName = this.imgData[this.i].name;
}
this.checkId=this.i
this.handlePrevmin()
},
// 切换到下一张
handleNext() {
let _this = this;
this.$refs.bigImg.style.transform = "rotate(0deg)";
this.rotateDeg = 0;
this.i++;
if (this.i === this.imgData.length) {
_this.tips("已经是最后一张了!");
_this.i = Number(this.imgData.length) - 1;
} else {
this.bigImgUrl = this.imgData[this.i].url;
this.imgIndex = this.i + 1;
this.bigImgName = this.imgData[this.i].name;
}
this.checkId=this.i
this.handleNextmin()
},
handlePrevmin() {
let _this = this;
this.p--;
if (this.p > 0) {
this.$refs.slip.style.marginTop = (this.p - 1) * -80 + "px";
} else {
this.p = 0;
}
},
handleNextmin() {
let _this = this;
this.p++;
if (this.p < this.imgData.length - 5) {
this.$refs.slip.style.marginTop = this.p * -80 + "px";
} else {
this.p = this.imgData.length - 5;
}
},
// 提示框
tips(msg) {
let _this = this;
_this.showTips = true;
_this.tipsText = msg;
setTimeout(function() {
_this.showTips = false;
}, 1000);
},
// 下载图片
downloadImg(data, filename) {
const save_link = document.createElementNS(
"http://www.w3.org/1999/xhtml",
"a"
);
save_link.href = "api/uploadsfile/" + data;
save_link.download = filename;
const event = document.createEvent("MouseEvents");
event.initMouseEvent(
"click",
true,
false,
window,
0,
0,
0,
0,
0,
false,
false,
false,
false,
0,
null
);
save_link.dispatchEvent(event);
}
}
};
</script>
<style lang="scss" scoped>
.imgDialog .el-dialog__body {
padding: 0;
height: 100%;
}
.wrapper {
position: relative;
display: flex;
flex-direction: column;
}
i {
cursor: pointer;
}
.imgName {
width: 100%;
height: 40px;
background: rgba(0, 0, 0, 0.5);
color: #fff;
line-height: 40px;
}
.imgName .left {
display: inline-block;
width: 10%;
padding-left: 20px;
}
.imgName .center {
display: inline-block;
width: 80%;
text-align: center;
}
.imgName .closeBtn {
position: absolute;
top: 0;
right: 20px;
}
.imgName .closeBtn i {
font-size: 20px !important;
}
.leftArrow {
width: 30px;
height: 30px;
border: 1px solid #fff;
border-radius: 50%;
background: rgba(0, 0, 0, 0.5);
z-index: 1;
}
.rightArrow {
width: 30px;
height: 30px;
border: 1px solid #fff;
background: rgba(0, 0, 0, 0.5);
border-radius: 50%;
}
.content {
flex-grow: 1;
position: relative;
display: flex;
height: 100%;
justify-content: space-between;
align-items: center;
.left-content {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
}
.imgContainer {
height: 100%;
text-align: center;
overflow: auto;
align-items: center;
display: flex;
.bigImg {
width: 372px;
height: 526px;
}
.tips {
padding: 10px;
background: rgba(0, 0, 0, 0.7);
color: #fff;
text-align: center;
line-height: 40px;
position: absolute;
left: 50%;
top: 50%;
margin-left: -60px;
margin-top: -20px;
border-radius: 6px;
padding: 4px 8px;
font-size: 14px;
}
}
.handleContainer {
width: 345px;
margin: 0 auto;
height: 40px;
line-height: 40px;
border-radius: 20px;
background: rgba(0, 0, 0, 0.6);
ul {
padding: 0;
margin: 0;
li {
list-style: none;
display: inline-block;
width: 30px;
height: 30px;
margin-left: 20px;
cursor: pointer;
font-size: 0;
i {
font-size: 30px;
padding-top: 5px;
color: #fff;
}
}
}
}
.thumbnailContainer {
padding: 10px;
height: 100%;
background: rgba(0, 0, 0, 0.5);
overflow: hidden;
transform: translate(-0%, 0%);
}
.thumbnailContainer .view {
overflow: hidden;
display: flex;
height: 100%;
padding-top: 20px;
padding-bottom: 15px;
flex-direction: column;
align-items: center;
position: relative;
ul {
display: flex;
padding: 0;
margin: 0;
flex-direction: column;
align-items: center;
overflow: hidden;
}
.checkImg{
border-top:3px solid red;
border-bottom:3px solid red;
}
}
.thumbnailContainer ul li {
display: inline-block;
width: 60px;
height: 60px;
margin: 0;
margin-top: 20px;
}
.thumbnailContainer ul li:first-child {
margin: 0;
}
.thumbnailContainer ul li img {
display: inline-block;
width: 60px;
height: 60px;
box-sizing: content-box;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.6s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
.cancelselect {
-moz-user-select: none; /*火狐*/
-webkit-user-select: none; /*webkit浏览器*/
-ms-user-select: none; /*IE10*/
-khtml-user-select: none; /*早期浏览器*/
user-select: none;
}
</style>
引用
<el-dialog :title="viewTitle||'预览'" :visible.sync="visible" width="70%" custom-class="imgDialog" :fullscreen="true" v-dialogDrag>
<vue-picture-viewer :imgData="temp.fileList" :switch="true" v-if="visible" :propsId='propsId' :viewTitle='viewTitle'>
</vue-picture-viewer>
</el-dialog>
即可