自己封装的定制化图片预览组件
1、针对Vue2,
2、支持图片列表切换、图片的旋转、放大、缩小、全屏
3、定制化:显示当前图片的名称,样式自定义
0、效果图
一、图片预览组件
<template>
<div class="image-preview-box" :style="{
top:`${imagePreviewBox.top}%`,
right: `${imagePreviewBox.right}%`,
left: `${imagePreviewBox.left}%`,
bottom: `${imagePreviewBox.bottom}%`
}">
<!-- 图片预览封装 带图片名称的 -->
<div class="tit-box">
<!-- 中间名称 -->
<div class="center-tit">{{currentImageName}}</div>
<!-- 右边的关闭按钮 -->
<div class="right-close-icon image-viewer__btn" @click="closePreviewBox">X</div>
</div>
<!-- 图片预览盒子 -->
<div class="image-preview-list-box">
<!-- 图片预览列表 -->
<ul class="image-preview-list">
<li>
<!-- 易错点: :style="{transform: `rotateZ(${currentImageRotateZ}deg)`}" -->
<img :style="{transform: `rotateZ(${currentImageRotateZ}deg)`}" ref="imagePreviewList" :src="currentImageSrc" alt="">
</li>
</ul>
<!-- 切换 按钮 -->
<div @click="arrowFn('left')" class="left-arrow image-viewer__btn"><a-icon type="left" /></div>
<div @click="arrowFn('right')" class="right-arrow image-viewer__btn"><a-icon type="right" /></div>
</div>
<!-- 操作图片盒子 -->
<div class="image-viewer__actions image-viewer__btn">
<div class="image-viewer__actions__inner">
<!-- 放小镜 -->
<a-icon title="缩小" @click="zoomFn('out')" type="zoom-out" />
<!-- 放大镜 -->
<a-icon title="放大" @click="zoomFn('in')" type="zoom-in" />
<!-- 全屏 缩小:<a-icon type="fullscreen-exit" /> -->
<a-icon :title="isFullscreen === 'fullscreen-exit' ? '小屏' : '全屏'" @click="zoomFn(isFullscreen)" :type="isFullscreen" />
<!-- 向左旋转 -->
<a-icon title="左旋转" @click="zoomFn('undo')" type="undo" />
<!-- 向右旋转 -->
<a-icon title="右旋转" @click="zoomFn('redo')" type="redo" />
</div>
</div>
</div>
</template>
<script>
export default {
props : ["currentPreviewId"],
data() {
return {
currentImageIndex : 0, // 当前图片的索引
currentImageSrc : "", // 保存当前图片
currentImageName : "", // 保存当前图片名称
isFullscreen : "fullscreen",
currentImageRotateZ : 0, // 保存图片的旋转角度
imagePreviewBox : { // 保存预览盒子的大小
top:24,
right: 16.5,
left: 16.5,
bottom: 9
}
}
},
watch : {
currentPreviewId : {
handler(newCurrentPreviewImgId) {
if(newCurrentPreviewImgId) {
// savePreviewImg
this.$parent.savePreviewImg.forEach((item,index)=>{
if(item.id === newCurrentPreviewImgId) {
this.currentImageIndex = index;
// this.currentImageSrc = item.coverUrl;
// this.currentImageName = item.fileName.slice(0,item.fileName.lastIndexOf('.'));
return;
}
})
}
},
immediate : true
},
currentImageIndex : {
handler() {
this.currentImageSrc = this.$parent.savePreviewImg[this.currentImageIndex].coverUrl;
this.currentImageName = this.$parent.savePreviewImg[this.currentImageIndex].fileName.slice(0,this.$parent.savePreviewImg[this.currentImageIndex].fileName.lastIndexOf('.'));
},
immediate : true
}
},
methods: {
// 操作预览图片
zoomFn(msg) {
switch(msg) {
// 放小镜
case "out" :
this.imagePreviewBox.top >= 24 ? this.imagePreviewBox.top = 24 : this.imagePreviewBox.top += 6;
this.imagePreviewBox.right >= 3.2 ? this.imagePreviewBox.right = 16.5 : this.imagePreviewBox.right += 3.2;
this.imagePreviewBox.left >= 3.2 ? this.imagePreviewBox.left = 16.5 : this.imagePreviewBox.left += 3.2;
this.imagePreviewBox.bottom >= 9 ? this.imagePreviewBox.bottom = 9 : this.imagePreviewBox.bottom += 2.4;
this.isFullscreen = "fullscreen";
break;
// 放大镜
case "in" :
this.imagePreviewBox.top <= 0 ? this.imagePreviewBox.top = 0 : this.imagePreviewBox.top -= 6;
this.imagePreviewBox.right <= 3.2 ? this.imagePreviewBox.right = 0 : this.imagePreviewBox.right -= 3.2;
this.imagePreviewBox.left <= 3.2 ? this.imagePreviewBox.left = 0 : this.imagePreviewBox.left -= 3.2;
this.imagePreviewBox.bottom <= 0 ? this.imagePreviewBox.bottom = 0 : this.imagePreviewBox.bottom -= 2.4;
this.isFullscreen = this.imagePreviewBox.top === 0 && this.imagePreviewBox.right === 0 && this.imagePreviewBox.bottom === 0 ? "fullscreen-exit" : "fullscreen";
break;
// 小屏 切到 大屏
case "fullscreen" :
this.isFullscreen = "fullscreen-exit";
this.imagePreviewBox = {
top : 0,
left : 0,
right : 0,
bottom : 0
};
break;
// 退出全屏
case "fullscreen-exit" :
this.isFullscreen = "fullscreen";
this.imagePreviewBox = {
top : 24,
left : 16.5,
right : 16.5,
bottom : 9
};
break;
// 左旋转 transform: rotateZ('angle');
case "undo" :
this.currentImageRotateZ === -360 ? this.currentImageRotateZ = 0 : this.currentImageRotateZ -= 90;
break;
// 右旋转
case "redo" :
this.currentImageRotateZ === 360 ? this.currentImageRotateZ = 0 : this.currentImageRotateZ += 90;
break;
}
},
closePreviewBox() {
this.$parent.isShowImgPreview = false;
},
arrowFn(arrow) {
// savePreviewImg 图片预览的列表
if(arrow === "right") {
// 向右
if(this.currentImageIndex === this.$parent.savePreviewImg.length - 1) {
this.currentImageIndex = 0;
} else {
this.currentImageIndex++;
}
} else if(arrow === "left") {
// 向左
if(this.currentImageIndex === 0) {
this.currentImageIndex = this.$parent.savePreviewImg.length - 1;
} else {
this.currentImageIndex--;
}
}
}
},
};
</script>
<style scoped>
.image-preview-box {
position: fixed;
background-color: #fff;
z-index: 999;
border: 1px solid #EBEBEB;
}
.image-preview-box .tit-box {
height: 3%;
width: 100%;
}
.image-preview-box .image-preview-list-box {
width: 100%;
height: 75%;
position: relative;
}
.image-preview-list-box .left-arrow,
.image-preview-list-box .right-arrow {
width: 35px;
height: 35px;
font-size: 18px;
color: #fff;
background-color: #606266;
}
.image-preview-list-box .left-arrow {
position: absolute;
left: 10px;
top: 50%;
}
.image-preview-list-box .right-arrow {
position: absolute;
right: 10px;
top: 50%;
}
.image-preview-list {
width: 90%;
height: 100%;
margin: 15px auto;
}
.image-preview-list li,
.image-preview-list img {
width: 100%;
height: 100%;
object-fit: cover;
overflow: hidden;
}
.tit-box .center-tit {
text-align: center;
color: #595959;
font-weight: 700;
margin-top: 40px;
}
.right-close-icon {
top: 20px;
right: 20px;
width: 40px;
height: 40px;
font-size: 24px;
color: #fff;
background-color: #606266;
}
/* 定义所有操作按钮 */
.image-viewer__btn {
position: absolute;
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
opacity: 0.8;
cursor: pointer;
box-sizing: border-box;
user-select: none;
}
.image-viewer__actions {
left: 50%;
bottom: 20px;
transform: translateX(-50%);
width: 282px;
height: 44px;
padding: 0 23px;
background-color: #606266;
border-color: #fff;
border-radius: 22px;
}
.image-viewer__actions__inner {
width: 100%;
height: 100%;
text-align: justify;
cursor: default;
font-size: 23px;
color: #fff;
display: flex;
align-items: center;
justify-content: space-around;
}
.image-viewer__actions__inner .anticon {
cursor: pointer;
}
</style>
二、父级组件使用
引入注册后:
// 1、currentPreviewId : "" // 保存当前预览项的id
<ImgPreviewHasName :currentPreviewId="currentPreviewId" v-if="isShowImgPreview"></ImgPreviewHasName>
// 2、
<img @click="showImagePreview(item)" :src="item.coverUrl" alt="">