因为项目中需要能预览一系列图像,element-ui里面图像预览组件已不能满足自身需求,所以就自己仿照其封装了插件已满足需求,其中也用到了swiper:
npm install vue-awesome-swiper --save
在main.js中引用(注:也可在组件中引用)
import
VueAwesomeSwiper from
'vue-awesome-swiper'
Vue.use(VueAwesomeSwiper)
import
'swiper/dist/css/swiper.css'
(css需要单独引用)
一、效果图
- 能自定义swiper-slide内容块;
- 能放大、缩小、重置、左旋转、右旋转图像;
二、组件
<template>
<el-dialog class="preview-box" :visible.sync="isshow" width="100%" center>
<i @click="handleClose" class="el-icon-error close"></i>
<swiper ref="mySwiper" class="swiper-preview" :options="swiperOption">
<slot name="swiper-slide">
<swiper-slide v-for="(item,index) in list" :key="item.id">
<img :style="{transform:(index==activeIndex?style:'')}" :src="item.pic" alt />
<div class="result">
<span>({{index+1}}/{{list.length}})</span>
</div>
</swiper-slide>
</slot>
<div class="swiper-button-prev" slot="button-prev">
<i class="el-icon-arrow-left"></i>
</div>
<div class="swiper-button-next" slot="button-next">
<i class="el-icon-arrow-right"></i>
</div>
</swiper>
<div class="tool">
<i v-for="item in tools" :key="item.id" @click="handleTansform(item.id)" :class="item.icon"></i>
</div>
</el-dialog>
</template>
<script>
export default {
data() {
const vm = this;
return {
tools: [
{ icon: "el-icon-zoom-in", id: 1 },
{ icon: "el-icon-zoom-out", id: 2 },
{ icon: "el-icon-full-screen", id: 3 },
{ icon: "el-icon-refresh-left", id: 4 },
{ icon: "el-icon-refresh-right", id: 5 }
],
swiperOption: {
effect: "fade",
navigation: {
nextEl: ".swiper-button-next",
prevEl: ".swiper-button-prev"
},
on: {
click: function() {
vm.activeIndex = this.realIndex;
vm.scale = 1;
vm.rotate = 0;
vm.style = `scale(${this.scale}) rotate(${this.rotate}deg)`;
}
}
},
activeIndex: 0,
isshow: false,
list: [],
index: 0,
scale: 1,
rotate: 0,
style: "scale(1) rotate(0deg)"
};
},
methods: {
handleClose() {
this.scale = 1;
this.rotate = 0;
this.style = `scale(${this.scale}) rotate(${this.rotate}deg)`;
this.isshow = false;
},
handleTansform(idx) {
switch (idx) {
case 1:
if (this.scale < 5) this.scale += 0.1;
break;
case 2:
if (this.scale > 0.15) this.scale -= 0.1;
break;
case 3:
this.scale = 1;
this.rotate = 0;
break;
case 4:
this.rotate -= 90;
break;
case 5:
this.rotate += 90;
break;
default:
break;
}
this.style = `scale(${this.scale}) rotate(${this.rotate}deg)`;
},
handleScroll(e) {
let direction = e.deltaY > 0 ? 2 : 1; //该语句可以用来判断滚轮是向上滑动还是向下
this.handleTansform(direction);
}
},
mounted() {
window.addEventListener("mousewheel", this.handleScroll, false);
},
created() {
this.$bus.$on("isPreviewImg", data => {
this.isshow = true;
this.list = data.list;
this.index = data.index;
this.activeIndex = data.index;
});
},
watch: {
index(n) {
this.$nextTick(function() {
this.$refs.mySwiper.swiper.slideTo(n, 1000, true);
});
}
}
};
</script>
<style lang="scss" >
//注:博主项目需要适配大屏所以css样式普遍偏大,请自行调整样式大小
@import "../assets/base";
.preview-box {
width: 100%;
height: 100%;
overflow: hidden;
.el-dialog {
margin: 0 !important;
background: transparent;
width: 100%;
height: 100%;
.el-dialog__header {
display: none;
}
.el-dialog__body {
width: 100%;
height: 100%;
padding: 0;
position: relative;
.close {
z-index: 3000;
cursor: pointer;
position: absolute;
right: 100px;
top: 100px;
font-size: 60px;
color: $color;
}
.tool {
z-index: 3000;
height: 60px;
width: 500px;
border-radius: 60px;
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
background: rgba($color: $color, $alpha: 0.8);
color: #fff;
font-size: 40px;
@include flexx;
justify-content: space-around;
i {
cursor: pointer;
}
}
.swiper-preview {
width: 100%;
height: 100%;
.swiper-slide {
position: relative;
align-items: center;
justify-content: center;
display: flex;
flex-direction: column;
opacity: 0 !important;
overflow: hidden;
img {
transition: transform 0.3s ease 0s;
}
.result {
width: 100%;
height: 50px;
line-height: 50px;
background: $bg;
position: absolute;
top: 0px;
left: 50%;
transform: translateX(-50%);
color: #fff;
text-align: center;
}
}
.swiper-slide-active {
opacity: 1 !important;
}
.swiper-button-prev,
.swiper-button-next {
background: $color;
width: 60px;
height: 60px;
border-radius: 50%;
@include flexx;
justify-content: center;
color: #fff;
font-size: 40px;
}
}
}
}
}
</style>
三、在全局或者页面中注册该组件
四、在需要预览图像的地方调用方法:
methods: {
handlePreview() {
let data = {
index: 1,//默认显示图像数组第几张图片,从0到list.length
list: [ //需要预览的图像数组
{id:1,pic:require("../assets/images/i.jpg")},
{id:2,pic:require("../assets/images/noLesion.png")}
]
};
this.$bus.$emit("isPreviewImg", data);
},
}
五、在main.js中注册eventBus
Vue.prototype.$bus = new Vue();