1.效果图
2.代码实现
## 1.utils下建立img-preview
## 2.img-preview下建立index.js img-preview.vue
## 3.main.js引用
main.js
import imgPreviewPlugin from "@/utils/img-preview/index";
Vue.use(imgPreviewPlugin);
index.js
import imgPreview from "./img-preview.vue";
const imgPreviewPlugin = {
install(Vue) {
const imgPreviewConstructor = Vue.extend(imgPreview);
let imgPreviewInstance;
Vue.prototype.$imgShow = function (url) {
if (!imgPreviewInstance) {
imgPreviewInstance = new imgPreviewConstructor({
el: document.createElement("div"),
data() {
return {
imgUrl: url
};
}
});
document.body.appendChild(imgPreviewInstance.$el);
}
};
Vue.prototype.$imgClose = function () {
if (imgPreviewInstance) {
imgPreviewInstance.$destroy();
imgPreviewInstance.$el.parentNode.removeChild(imgPreviewInstance.$el);
imgPreviewInstance = null;
}
};
}
};
export default imgPreviewPlugin;
img-preview.vue
<template>
<transition appear>
<div class="img-prevew" v-show="imgPrevewShow">
<div class="main-content" @click.self="closeImg">
<div class="close-icno">
<a-icon type="close-circle" class="icon" @click.stop="closeImg"/>
</div>
<img
class="img-content"
:src="imgUrl"
alt=""
:style="`transform: scale(${imgScale})`"
>
<div class="navbtns">
<a-icon type="zoom-in" @click.stop="changeSize(0.15)" class="icon" />
<a-icon type="zoom-out" @click.stop="changeSize(-0.15)" class="icon" />
<a-icon :type="imgScale > 1 ? 'fullscreen-exit' : 'fullscreen'" @click.stop="recoverSize" class="icon"/>
</div>
</div>
</div>
</transition>
</template>
<script>
export default {
name: '',
data() {
return {
imgUrl:'',
imgScale:1,
imgPrevewShow:true,
}
},
methods: {
closeImg(){
this.imgPrevewShow = false;
setTimeout(()=>{
this.$imgClose();
},500)
},
changeSize(num){
if (this.imgScale <= 0.2 && num < 0) return
this.imgScale += num
},
recoverSize(){
if( this.imgScale === 1){
this.imgScale = 1.4;
}else{
this.imgScale = 1;
}
},
// 鼠标滚轮缩放
scrollFunc(e) {
e = e || window.event
// e.returnValue = false // ie
// 火狐下没有wheelDelta,用detail代替,由于detail值的正负和wheelDelta相反,所以取反
e.delta = e.wheelDelta || -e.detail
e.preventDefault()
if (e.delta > 0) {
//当滑轮向上滚动时
this.changeSize(0.05)
}
if (e.delta < 0) {
//当滑轮向下滚动时
this.changeSize(-0.05)
}
},
},
mounted() {
window.addEventListener('mousewheel', this.scrollFunc,{passive:false})
},
beforeDestroy() {
window.removeEventListener('mousewheel', this.scrollFunc);
},
}
</script>
<style lang="less" scoped>
/* 进入:始状态 */
.v-enter {
transform: translateY(-100%);
}
/* 进入:末状态 */
.v-enter-to {
transform: translateY(0);
}
/* 进入动画 */
.v-enter-active {
transition: 0.5s;
}
/* 离开:始状态 */
.v-leave {
transform: translateY(0);
}
/* 离开:末状态 */
.v-leave-to {
transform: translateY(-100%);
}
/* 离开动画 */
.v-leave-active {
transition: 0.5s;
}
.img-prevew{
position: fixed;
top: 0;
bottom: 0;
right: 0;
left: 0;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
z-index: 9999;
color: rgba(255,255,255,0.7);
}
.main-content{
height: 100%;
width: 100%;
position: relative;
background-color: rgba(0,0,0,0.7);
display: flex;
align-items: center;
justify-content: center;
.img-content{
transition: all 0.2s;
max-width: 100vw !important;
}
}
.close-icno{
z-index: 10000;
position: absolute;
top: 50px;
right: 50px;
.icon{
font-size: 30px;
cursor: pointer;
transition: all 0.3s;
}
.icon:hover{
color: white;
transform: rotate(180deg);
}
}
.navbtns{
position: absolute;
bottom: 100px;
left: 0 ;
right: 0;
margin: 0 auto;
height: 50px;
width: 200px;
background-color: black;
opacity: 0.8;
border-radius: 25px ;
z-index: 10000;
display: flex;
align-items: center;
justify-content: center;
.icon{
font-size: 30px;
transition: all 0.3s;
margin: 0 10px;
cursor: pointer;
}
.icon:hover{
color: white;
transform: scale(1.1);
}
}
</style>
3.优雅的调用
//封装后
owner.getHtmlImgSrc = (e)=>{
if (e.target.tagName.toUpperCase() === 'IMG') {
Vue.prototype.$imgShow(e.target.src)
}
}
//直接使用
this.$imgShow('图片的URL')