<template>
|
<div
|
class="app_image"
|
id="app-image"
|
>
|
<div class="header">
|
<b>{{ title }}</b>
|
<span
|
class="close"
|
@click.stop="onClose"
|
><i class="el-icon-close"></i></span>
|
</div>
|
<div class="main">
|
<img
|
:src="pic"
|
alt=""
|
:style="imgSty"
|
/>
|
</div>
|
<div
|
class="list"
|
:class="{ show: showMenu }"
|
>
|
<v-tool-scroll ids="image-scroll">
|
<ul>
|
<li
|
v-for="(i, j) in list"
|
:key="j + '-image-list'"
|
@click.stop="onDetail(i)"
|
>
|
<img
|
:src="i.img"
|
alt=""
|
/>
|
</li>
|
</ul>
|
</v-tool-scroll>
|
</div>
|
<div
|
class="tool"
|
v-if="tool"
|
>
|
<span
|
class="up"
|
@click.stop="onScale(1)"
|
><i class="el-icon-circle-plus-outline"></i></span>
|
<span
|
class="down"
|
@click.stop="onScale(0)"
|
><i class="el-icon-remove-outline"></i></span>
|
<span
|
class="menu"
|
v-if="list.length > 0"
|
@click.stop="showMenu = !showMenu"
|
><i class="el-icon-s-grid"></i></span>
|
<span
|
class="hidden"
|
v-else
|
></span>
|
<span
|
class="hidden"
|
v-if="val.d"
|
></span>
|
<span
|
@click.stop="onKey(0)"
|
v-if="val.d"
|
><i class="el-icon-top"></i></span>
|
<span
|
class="hidden"
|
v-if="val.d"
|
></span>
|
<span
|
@click.stop="onKey(3)"
|
v-if="val.d"
|
><i class="el-icon-back"></i></span>
|
<span
|
@click.stop="onReset"
|
v-if="val.r"
|
><i class="el-icon-refresh"></i></span>
|
<span
|
class="hidden"
|
v-else-if="val.d"
|
></span>
|
<span
|
@click.stop="onKey(1)"
|
v-if="val.d"
|
><i class="el-icon-right"></i></span>
|
<span
|
class="hidden"
|
v-if="val.d"
|
></span>
|
<span
|
@click.stop="onKey(2)"
|
v-if="val.d"
|
><i class="el-icon-bottom"></i></span>
|
<span
|
class="hidden"
|
v-if="val.d"
|
></span>
|
</div>
|
<span
|
class="pager"
|
v-if="list.length > 0 && showMenu"
|
>{{ index + 1 }}/{{ list.length }}</span>
|
<transition name="fade">
|
<div
|
class="detail"
|
v-if="detail"
|
>{{ desc }}</div>
|
</transition>
|
<div
|
class="footer"
|
v-if="foot"
|
>
|
<p class="desc text_overflow">{{ desc }}</p>
|
<span
|
class="more col_primary"
|
v-if="desc"
|
@click.stop="detail = !detail"
|
>{{ detail ? "关闭" : "详细" }}</span>
|
</div>
|
</div>
|
</template>
|
|
<script>
|
import { mapState } from "vuex";
|
export default {
|
props: {},
|
components: {},
|
computed: {
|
...mapState({ vuex_item: "image" }),
|
imgSty() {
|
return {
|
transform:
|
"scale(" +
|
this.scale +
|
") translateX(" +
|
this.tranX +
|
"px) translateY(" +
|
this.tranY +
|
"px)",
|
};
|
},
|
},
|
data() {
|
return {
|
title: "查看大图",
|
pic: "",
|
list: [],
|
item: [],
|
index: 0,
|
foot: false,
|
tool: false,
|
showMenu: false,
|
detail: false,
|
desc: "凯撒大帝啦是",
|
scale: 1,
|
tranX: 0,
|
tranY: 0,
|
val: { s: 0.1, x: 1, y: 1, r: false, d: false, k: false },
|
};
|
},
|
watch: {
|
vuex_item: {
|
handler(n) {
|
this.setItem(n);
|
},
|
deep: true,
|
},
|
showMenu() {
|
this.detail = false;
|
},
|
},
|
methods: {
|
onKey(v) {
|
this.showMenu = false;
|
switch (+v) {
|
case 0:
|
this.tranY -= this.val.y / this.scale;
|
break;
|
case 1:
|
this.tranX += this.val.x / this.scale;
|
break;
|
case 2:
|
this.tranY += this.val.y / this.scale;
|
break;
|
case 3:
|
this.tranX -= this.val.x / this.scale;
|
break;
|
default:
|
}
|
},
|
onReset() {
|
this.scale = 1;
|
this.tranX = 0;
|
this.tranY = 0;
|
},
|
onClose() {
|
this.$store.dispatch("setImage", { time: demo.rand(-999, -10) });
|
},
|
onScale(v) {
|
this.detail = false;
|
if (!!v) {
|
this.scale += this.val.s;
|
} else {
|
this.scale -= this.val.s;
|
this.scale = this.scale < 0.1 ? 0.1 : this.scale;
|
}
|
},
|
onDetail(i) {
|
this.scale = 1;
|
this.detail = false;
|
this.index = i.index || 0;
|
this.title = i.title || "[大图]";
|
this.desc = i.desc || "";
|
this.pic = i.img;
|
this.onReset();
|
},
|
setItem(n) {
|
if (n.title) {
|
this.title = n.title;
|
}
|
this.desc = "";
|
this.foot = n.foot > 0;
|
this.tool = n.tool > 0;
|
if (n.pic) {
|
this.pic = n.pic;
|
this.$nextTick(() => {
|
if (this.list.length && this.list[0].img) {
|
let desc = this.list.filter((r) => {
|
return r.img === n.pic;
|
});
|
if (desc.length) {
|
this.desc = desc[0].desc;
|
}
|
}
|
});
|
}
|
if (n.list && n.list.length && demo._is_obj(n.list).code === 4) {
|
let ts = this;
|
ts.list = n.list.map((k, v) => {
|
let c = demo._is_obj(k).code === 6;
|
return {
|
index: v,
|
img: c ? k.img : k,
|
desc: c ? k.desc : "",
|
title: c ? k.title : "",
|
};
|
});
|
let v = this.list.filter((k) => {
|
return k.img === ts.pic;
|
});
|
if (v.length) {
|
ts.index = v[0].index;
|
}
|
ts.item = n.list;
|
}
|
},
|
// 键盘事件
|
dropDown() {
|
if (!this.val.k) return 0;
|
let ts = this;
|
demo.$ctrl.k("#app-image", (e) => {
|
switch (e.val) {
|
case 13:
|
case 101:
|
ts.onReset();
|
break;
|
case 107:
|
ts.onScale(1);
|
break;
|
case 109:
|
ts.onScale(0);
|
break;
|
case 27:
|
ts.onClose();
|
break;
|
case 96:
|
if (ts.list.length) {
|
ts.showMenu = !ts.showMenu;
|
}
|
break;
|
case 110:
|
if (ts.desc) {
|
ts.detail = !ts.detail;
|
}
|
break;
|
default:
|
ts.onKey(e.code);
|
}
|
});
|
},
|
toNumber(v, n) {
|
if (isNaN(v) || !v || v === "") {
|
return n || 1;
|
}
|
return +v;
|
},
|
},
|
mounted() {
|
let val = demo.$local.get("image-watch-scale") || 0.1;
|
let x = demo.$local.get("image-watch-x") || 1;
|
let y = demo.$local.get("image-watch-y") || 1;
|
this.val = {
|
s: this.toNumber(val, 0.1),
|
x: this.toNumber(x),
|
y: this.toNumber(y),
|
r: demo.$local.get("image-watch-reset") || false,
|
d: demo.$local.get("image-watch-dire") || false,
|
k: demo.$local.get("image-watch-key") || false,
|
};
|
this.setItem(this.vuex_item);
|
this.$nextTick(() => {
|
let id = "#app-image";
|
demo.move(id, (e) => {
|
if (e.code) {
|
demo.$.dom(id).style.left = e.left;
|
demo.$.dom(id).style.top = e.top;
|
}
|
});
|
this.dropDown();
|
});
|
},
|
};
|
</script>
|
<style lang='less' scoped>
|
.app_image {
|
font-size: 14px;
|
color: #333;
|
position: fixed;
|
z-index: 2200;
|
width: 70%;
|
height: 60%;
|
background-color: #fff;
|
border-radius: 10px;
|
box-sizing: border-box;
|
left: 15%;
|
top: 20%;
|
box-shadow: 0 0 10px #ccc;
|
overflow: hidden;
|
.header {
|
padding: 0 15px;
|
height: 40px;
|
position: relative;
|
line-height: 40px;
|
border-bottom: 1px solid #eee;
|
z-index: 2205;
|
background-color: #fff;
|
b {
|
font-weight: 700;
|
}
|
.close {
|
position: absolute;
|
right: 0;
|
top: 0;
|
width: 40px;
|
height: 40px;
|
text-align: center;
|
font-size: 18px;
|
color: tomato;
|
cursor: pointer;
|
}
|
}
|
.detail {
|
position: absolute;
|
z-index: 2205;
|
width: 80%;
|
height: 60%;
|
left: 10%;
|
top: 20%;
|
color: #fff;
|
box-sizing: border-box;
|
border-radius: 10px;
|
font-size: 16px;
|
line-height: 1.2;
|
padding: 20px;
|
background-color: rgba(47, 47, 48, 0.6);
|
word-break: break-all;
|
transition: all 0.3s;
|
&:hover {
|
background-color: rgba(47, 47, 48, 0.8);
|
z-index: 2210;
|
}
|
}
|
.pager {
|
position: absolute;
|
z-index: 2205;
|
right: 10px;
|
bottom: 50px;
|
padding: 10px;
|
font-size: 22px;
|
color: #fff;
|
background-color: rgba(34, 34, 34, 0.2);
|
border-radius: 8px;
|
}
|
.tool {
|
position: absolute;
|
z-index: 2205;
|
right: 10px;
|
top: 50px;
|
display: flex;
|
width: 110px;
|
flex-wrap: wrap;
|
span {
|
font-size: 24px;
|
line-height: 30px;
|
text-align: center;
|
width: 30px;
|
height: 30px;
|
border-radius: 5px;
|
background-color: #fff;
|
margin-left: 5px;
|
box-shadow: 0 0 5px #ccc;
|
margin-bottom: 5px;
|
cursor: pointer;
|
&:active {
|
box-shadow: 0 0 0 #ccc;
|
}
|
&.hidden {
|
opacity: 0;
|
cursor: default;
|
background-color: transparent;
|
}
|
}
|
}
|
.list {
|
height: calc(~"100% - 40px");
|
position: absolute;
|
left: 0;
|
bottom: 0;
|
background-color: #222;
|
z-index: 2208;
|
width: 200px;
|
transition: all 0.5s;
|
transform: translateX(-200px);
|
&.show {
|
transform: translateX(0);
|
}
|
li {
|
height: 120px;
|
box-sizing: border-box;
|
padding: 5px;
|
cursor: pointer;
|
img {
|
display: block;
|
width: 100%;
|
height: 100%;
|
}
|
}
|
}
|
.main {
|
height: calc(~"100% - 40px");
|
position: relative;
|
z-index: 2201;
|
img {
|
position: absolute;
|
max-width: 90%;
|
max-height: 90%;
|
left: 0;
|
right: 0;
|
bottom: 0;
|
top: 0;
|
margin: auto;
|
transition: all 0.3s;
|
width: auto;
|
height: auto;
|
}
|
}
|
.footer {
|
position: absolute;
|
left: 0;
|
bottom: 0;
|
height: 40px;
|
width: 100%;
|
background-color: rgba(204, 204, 204, 0.3);
|
z-index: 2202;
|
display: flex;
|
font-size: 13px;
|
box-sizing: border-box;
|
padding: 8px;
|
line-height: 24px;
|
.desc {
|
width: calc(~"100% - 80px");
|
color: #666;
|
letter-spacing: 1px;
|
}
|
.more {
|
text-align: center;
|
width: 80px;
|
cursor: pointer;
|
}
|
}
|
}
|
</style>
|