nuxt_site/components/Popup/ImagePreview.vue
2024-05-02 21:28:18 +08:00

114 lines
2.2 KiB
Vue

<template>
<div @click="closePreview" :class="{ preview__container: true, hidden: hidden }">
<div @click.stop="toLeft" class="arrow-left"></div>
<div @click.stop="" class="preview__container__image">
<img loading="lazy" :src="src" alt="">
</div>
<div @click.stop="toRight" class="arrow-right"></div>
</div>
</template>
<script setup>
const props = defineProps(['modelValue', 'images'])
const emit = defineEmits(['update:modelValue'])
const src = ref("");
let idx = 0
const openPreview = () => {
document.body.style.overflow = 'hidden'
let index = props.images.indexOf(props.modelValue)
if (index !== -1) {
idx = props.images.indexOf(props.modelValue)
}
src.value = props.images[idx]
}
const closePreview = () => {
document.body.style.overflow = 'auto'
src.value = ""
emit('update:modelValue', src.value)
}
const hidden = computed(() => {
return props.modelValue.length === 0
})
watch(() => props.modelValue, (val) => {
if (val.length > 0) {
openPreview()
}
})
const toLeft = () => {
if (idx === 0) {
idx = props.images.length - 1
} else {
idx--
}
src.value = props.images[idx]
}
const toRight = () => {
if (idx === props.images.length - 1) {
idx = 0
} else {
idx++
}
src.value = props.images[idx]
}
</script>
<style lang="scss">
.preview__container {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 1000;
background-color: rgba(11, 11, 11, 0.7);
&.hidden {
display: none;
}
}
.preview__container__image {
&>img {
max-width: 100%;
max-height: 767px;
user-select: none;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
.arrow-left,
.arrow-right {
width: 30px;
height: 30px;
border-top: 18px solid transparent;
border-bottom: 18px solid transparent;
position: fixed;
top: 50%;
cursor: pointer;
z-index: 3;
}
.arrow-right {
border-left: 18px solid #BBBBBB;
right: 5%;
transform: translateY(-50%);
}
.arrow-left {
border-right: 18px solid #BBBBBB;
left: 5%;
transform: translateY(-50%);
}
</style>