323 lines
8.6 KiB
Vue
323 lines
8.6 KiB
Vue
<template>
|
||
<div
|
||
class="img-review-wrapper"
|
||
v-show="imgReviewVisible"
|
||
@click.self="closeImgReview"
|
||
@mousewheel.prevent="rollImg()"
|
||
>
|
||
<!-- 顶部信息栏 & 工具栏 -->
|
||
<div class="tip-wrapper" v-if="imgReviewVisible">
|
||
<div class="name" :title="activeFileName + activeExtendName">{{ activeFileName }}.{{ activeExtendName }}</div>
|
||
<div class="opera-btn-group">
|
||
<el-input-number v-model="inputActiveIndex" :min="1" :max="imgReviewList.length" size="mini"></el-input-number>
|
||
<span class="split-line">/</span>{{ imgReviewList.length }}
|
||
</div>
|
||
<div class="tool-wrapper">
|
||
<i class="item el-icon-refresh-right" title="向右旋转" @click="rotateImg"></i>
|
||
<a
|
||
class="item download-link"
|
||
target="_blank"
|
||
:href="activeDownloadLink"
|
||
:download="activeFileName + '.' + activeExtendName"
|
||
>
|
||
<i class="el-icon-download" title="保存到本地"></i>
|
||
</a>
|
||
<el-tooltip effect="dark" placement="bottom">
|
||
<div slot="content">
|
||
操作提示:<br />
|
||
点击图片以外的区域可退出查看;<br />
|
||
按Esc键可退出查看;<br />
|
||
鼠标滚轮可放大缩小图片
|
||
</div>
|
||
<div class="item text-wrapper">
|
||
<span class="text">操作提示</span>
|
||
<i class="el-icon-question"></i>
|
||
</div>
|
||
</el-tooltip>
|
||
</div>
|
||
</div>
|
||
<!-- 大图查看 -->
|
||
<img
|
||
class="img-large"
|
||
ref="imgLarge"
|
||
v-for="(item, index) in imgReviewList"
|
||
:key="index"
|
||
:src="item.fileUrl"
|
||
v-show="index === activeIndex"
|
||
/>
|
||
<!-- 左右切换图标 -->
|
||
<i class="pre-icon el-icon-arrow-left" title="上一张" v-show="activeIndex > 0" @click.stop="activeIndex--"></i>
|
||
<i
|
||
class="next-icon el-icon-arrow-right"
|
||
title="下一张"
|
||
v-show="activeIndex < imgReviewList.length - 1"
|
||
@click.stop="activeIndex++"
|
||
></i>
|
||
<!-- 底部显示放大缩小比例 -->
|
||
<div class="zoom-bar">
|
||
<el-slider
|
||
v-model="imgZoom"
|
||
:min="imgZoomMin"
|
||
:max="imgZoomMax"
|
||
:format-tooltip="formatZoom"
|
||
@input="changeZoom"
|
||
></el-slider>
|
||
<div class="zoom-count">{{ imgZoom }}%</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
name: 'ImgReview',
|
||
data() {
|
||
return {
|
||
rotate: 0, // 旋转角度
|
||
activeIndex: 0, // 当前图片索引 从 0 开始
|
||
imgZoom: 40, // 图片缩放比例
|
||
imgZoomMin: 1, // 图片缩放最小比例
|
||
imgZoomMax: 200 // 图片缩放最大比例
|
||
}
|
||
},
|
||
computed: {
|
||
// 图片查看组件是否显示
|
||
imgReviewVisible() {
|
||
return this.$store.state.imgReview.imgReviewVisible
|
||
},
|
||
// 图片列表
|
||
imgReviewList() {
|
||
return this.$store.state.imgReview.imgReviewList
|
||
},
|
||
// 默认显示的图片索引 从 0 开始
|
||
defaultActiveIndex() {
|
||
return this.$store.state.imgReview.defaultActiveIndex
|
||
},
|
||
// 当前显示的图片名称
|
||
activeFileName() {
|
||
return this.imgReviewList[this.activeIndex].fileName
|
||
},
|
||
// 当前显示的图片扩展名
|
||
activeExtendName() {
|
||
return this.imgReviewList[this.activeIndex].extendName
|
||
},
|
||
// 对用户而言 显示的图片索引 从 1 开始 顶部栏输入框控制此值变化
|
||
inputActiveIndex: {
|
||
get() {
|
||
return this.activeIndex + 1
|
||
},
|
||
set(value) {
|
||
this.activeIndex = value - 1
|
||
}
|
||
},
|
||
// 当前显示的图片下载链接
|
||
activeDownloadLink() {
|
||
return this.imgReviewList[this.activeIndex].downloadLink
|
||
}
|
||
},
|
||
watch: {
|
||
// 监听 图片查看组件 显隐状态变化
|
||
imgReviewVisible(val) {
|
||
let body = document.querySelector('body')
|
||
if (val) {
|
||
this.activeIndex = this.defaultActiveIndex
|
||
// 挂在body下,防止组件元素有样式transform而使position: fixed失效
|
||
body.appendChild(this.$el)
|
||
body.style.overflow = 'hidden'
|
||
// 添加键盘Esc事件
|
||
this.$nextTick(() => {
|
||
document.addEventListener('keyup', (e) => {
|
||
if (e.keyCode === 27) {
|
||
this.closeImgReview()
|
||
}
|
||
})
|
||
})
|
||
this.$nextTick(() => {
|
||
this.$refs.imgLarge[this.activeIndex].style.zoom = '40%'
|
||
})
|
||
} else {
|
||
body.style.overflow = 'auto'
|
||
document.removeEventListener('keyup', (e) => {
|
||
if (e.keyCode === 27) {
|
||
this.closeImgReview()
|
||
}
|
||
})
|
||
}
|
||
},
|
||
// 监听 图片索引变化
|
||
activeIndex(newValue) {
|
||
this.rotate = 0
|
||
this.$nextTick(() => {
|
||
if (this.$refs.imgLarge[newValue].style.zoom) {
|
||
this.imgZoom = Number(this.$refs.imgLarge[newValue].style.zoom.split('%')[0])
|
||
} else {
|
||
this.$refs.imgLarge[newValue].style.zoom = '40%'
|
||
this.imgZoom = 40
|
||
}
|
||
})
|
||
}
|
||
},
|
||
methods: {
|
||
// 关闭图片预览
|
||
closeImgReview() {
|
||
this.$store.commit('setImgReviewData', { imgReviewVisible: false })
|
||
this.rotate = 0
|
||
this.$refs.imgLarge[this.activeIndex].style.transform = `rotate(${this.rotate}deg)`
|
||
},
|
||
// 格式化缩放数字 显示图片缩放比例
|
||
formatZoom(value) {
|
||
return value + '%'
|
||
},
|
||
// 图片缩放改变事件
|
||
changeZoom(value) {
|
||
if (this.$refs.imgLarge) {
|
||
this.$refs.imgLarge[this.activeIndex].style.zoom = value + '%'
|
||
}
|
||
},
|
||
// 缩放图片
|
||
rollImg() {
|
||
let zoom = parseInt(this.$refs.imgLarge[this.activeIndex].style.zoom) || 100
|
||
zoom += event.wheelDelta / 12
|
||
if (zoom >= this.imgZoomMin && zoom < this.imgZoomMax) {
|
||
this.imgZoom = zoom
|
||
this.$refs.imgLarge[this.activeIndex].style.zoom = zoom + '%'
|
||
}
|
||
return false
|
||
},
|
||
// 旋转图片
|
||
rotateImg() {
|
||
this.rotate += 90
|
||
this.$refs.imgLarge[this.activeIndex].style.transform = `rotate(${this.rotate}deg)`
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="stylus" scoped>
|
||
@import '../assets/style/varibles.styl'
|
||
|
||
.img-review-wrapper
|
||
position fixed
|
||
top 0
|
||
right 0
|
||
bottom 0
|
||
left 0
|
||
overflow auto
|
||
width 100%
|
||
height 100%
|
||
z-index 2010
|
||
text-align center
|
||
display flex
|
||
align-items center
|
||
animation imgReviewAnimation 0.3s
|
||
-webkit-animation imgReviewAnimation 0.3s /* Safari and Chrome */
|
||
animation-iteration-count 0.3
|
||
-webkit-animation-iteration-count 0.3
|
||
animation-fill-mode forwards
|
||
-webkit-animation-fill-mode forwards /* Safari 和 Chrome */
|
||
@keyframes imgReviewAnimation
|
||
0%
|
||
background transparent
|
||
100%
|
||
background rgba(0, 0, 0, 0.8)
|
||
@keyframes imgReviewAnimation
|
||
0%
|
||
background transparent
|
||
100%
|
||
background rgba(0, 0, 0, 0.8)
|
||
.tip-wrapper
|
||
position fixed
|
||
top 0
|
||
left 0
|
||
z-index 2011
|
||
background rgba(0, 0, 0, 0.5)
|
||
padding 0 48px
|
||
width calc(100% - 96px)
|
||
height 48px
|
||
line-height 48px
|
||
color #fff
|
||
font-size 16px
|
||
display flex
|
||
justify-content space-between
|
||
.name
|
||
flex 1
|
||
padding-right 16px
|
||
text-align left
|
||
overflow hidden
|
||
text-overflow ellipsis
|
||
white-space nowrap
|
||
.opera-btn-group
|
||
width 100px
|
||
display flex
|
||
>>> .el-input-number
|
||
width 40px
|
||
.el-input-number__decrease,
|
||
.el-input-number__increase
|
||
display none
|
||
.el-input__inner
|
||
margin-top 14px
|
||
background rgba(0, 0, 0, 0.5)
|
||
height 20px
|
||
line-height 20px
|
||
padding 0
|
||
font-size 16px
|
||
color #fff
|
||
.split-line
|
||
margin 0 8px
|
||
.tool-wrapper
|
||
flex 1
|
||
display flex
|
||
justify-content flex-end
|
||
.item
|
||
margin-left 16px
|
||
cursor pointer
|
||
&:hover
|
||
opacity 0.7
|
||
.el-icon-refresh-right
|
||
line-height 48px
|
||
font-size 18px
|
||
.download-link
|
||
color inherit
|
||
font-size 18px
|
||
.text-wrapper
|
||
margin-left 32px
|
||
.text
|
||
margin-right 8px
|
||
.img-large
|
||
margin 0 auto
|
||
transition transform 0.5s
|
||
-webkit-transition transform 0.5s /* Safari */
|
||
.pre-icon,
|
||
.next-icon
|
||
font-size 60px
|
||
color #fff
|
||
position fixed
|
||
top 50%
|
||
cursor pointer
|
||
&:hover
|
||
opacity 0.7
|
||
.pre-icon
|
||
left 64px
|
||
.next-icon
|
||
right 64px
|
||
.zoom-bar
|
||
position fixed
|
||
right 0
|
||
bottom 20px
|
||
left 0
|
||
margin 0 auto
|
||
width 600px
|
||
display flex
|
||
>>> .el-slider
|
||
flex 1
|
||
.el-slider__bar
|
||
background $PrimaryText
|
||
.el-slider__button
|
||
border-color $PrimaryText
|
||
.zoom-count
|
||
width 60px
|
||
height 38px
|
||
line-height 38px
|
||
text-align right
|
||
color #fff
|
||
</style>
|