Files
Mangarr/assets/vue/app/domain/reader/presentation/components/ReaderPage.vue

116 lines
3.1 KiB
Vue

<template>
<div class="page-container" :style="{ transform: `scale(${zoom})` }">
<div v-if="!pageData" class="error">Aucune donnée d'image disponible</div>
<div v-else-if="!pageData.base64Content" class="error">Contenu de l'image manquant</div>
<img
v-else
:src="imageSource"
:alt="`Page ${pageNumber}`"
class="page-image"
:style="imageStyle"
@load="handleImageLoad"
ref="imageRef" />
</div>
</template>
<script setup>
import { computed, onMounted, onUnmounted, ref } from 'vue';
const props = defineProps({
pageData: {
type: Object,
required: true
},
pageNumber: {
type: Number,
required: true
},
zoom: {
type: Number,
required: true
}
});
const imageRef = ref(null);
const naturalWidth = ref(0);
const naturalHeight = ref(0);
const windowWidth = ref(window.innerWidth);
const imageSource = computed(() => {
if (!props.pageData?.base64Content || !props.pageData?.mimeType) {
return '';
}
return `data:${props.pageData.mimeType};base64,${props.pageData.base64Content}`;
});
const handleImageLoad = () => {
if (imageRef.value) {
naturalWidth.value = imageRef.value.naturalWidth;
naturalHeight.value = imageRef.value.naturalHeight;
}
};
// Calculer la largeur maximale en fonction de la largeur disponible
const maxWidth = computed(() => {
if (!naturalWidth.value || !naturalHeight.value) return null;
const availableWidth = windowWidth.value;
// Si la largeur disponible est < 1200px : utiliser 95% de la largeur
if (availableWidth < 1200) {
return Math.min(naturalWidth.value, availableWidth * 0.95);
}
// Si la largeur disponible est >= 1200px : limiter à 1200px maximum
return Math.min(naturalWidth.value, 1200);
});
const imageStyle = computed(() => {
if (!maxWidth.value) return {};
return {
width: `${maxWidth.value}px`,
height: 'auto',
maxWidth: '100%'
};
});
// Gestion du redimensionnement de la fenêtre
const handleResize = () => {
windowWidth.value = window.innerWidth;
};
onMounted(() => {
if (imageRef.value && imageRef.value.complete) {
handleImageLoad();
}
window.addEventListener('resize', handleResize);
});
onUnmounted(() => {
window.removeEventListener('resize', handleResize);
});
</script>
<style lang="postcss" scoped>
.page-container {
@apply flex-1 flex items-center justify-center overflow-hidden;
transform-origin: center;
/* Réduction des marges sur mobile */
@apply p-0 sm:p-2;
}
.page-image {
@apply object-contain;
/* La largeur est gérée par le JavaScript, on garde juste les contraintes max */
max-width: 100%;
max-height: 100%;
}
.error {
@apply text-red-500 text-xl;
}
</style>