85 lines
1.6 KiB
Vue
85 lines
1.6 KiB
Vue
<template>
|
|
<img
|
|
:src="photoSrc()"
|
|
class="max-w-full h-full max-h-full"
|
|
loading="lazy"
|
|
decoding="async"
|
|
@click="openPreview"
|
|
/>
|
|
<div v-if="isPreviewVisible" class="modal" @click="closePreview">
|
|
<img :src="photoSrc()" alt="Preview" class="preview-image" />
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { Media } from "@/types";
|
|
import { defineComponent, nextTick, PropType, ref } from "vue";
|
|
|
|
export default defineComponent({
|
|
name: "MediaPhoto",
|
|
props: {
|
|
channel: { required: true },
|
|
media: {
|
|
type: Object as PropType<Media>,
|
|
required: true,
|
|
},
|
|
},
|
|
setup(props) {
|
|
const photoSrc = () => {
|
|
return `/medias/${props.channel}/${props.media.photo}`;
|
|
};
|
|
|
|
const isPreviewVisible = ref(false);
|
|
|
|
const openPreview = () => {
|
|
isPreviewVisible.value = true;
|
|
nextTick(() => {
|
|
const previewImage = document.querySelector(".preview-image");
|
|
if (previewImage) {
|
|
previewImage.requestFullscreen();
|
|
}
|
|
});
|
|
};
|
|
|
|
const closePreview = () => {
|
|
isPreviewVisible.value = false;
|
|
if (document.fullscreenElement) {
|
|
document.exitFullscreen();
|
|
}
|
|
};
|
|
|
|
return {
|
|
isPreviewVisible,
|
|
openPreview,
|
|
closePreview,
|
|
photoSrc,
|
|
};
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<style scoped>
|
|
.thumbnail {
|
|
cursor: pointer;
|
|
width: 200px;
|
|
/* Adjust as needed */
|
|
}
|
|
|
|
.modal {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: rgba(0, 0, 0, 0.8);
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
.preview-image {
|
|
max-width: 100%;
|
|
max-height: 100%;
|
|
}
|
|
</style>
|