merge
All checks were successful
Deploy / Deploy to Production (push) Successful in 15s

This commit is contained in:
isUnknown 2026-06-20 12:17:15 +02:00
parent 3aa46c7456
commit dd9e91c2d8
6 changed files with 251 additions and 5 deletions

View file

@ -0,0 +1,39 @@
/* Lightbox */
.lightbox {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.9);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
opacity: 0;
visibility: hidden;
transition: opacity 0.3s ease, visibility 0.3s ease;
&.open {
opacity: 1;
visibility: visible;
}
&__content {
display: flex;
justify-content: center;
align-items: center;
}
&__image {
width: 90vw;
height: 90vh;
object-fit: contain;
cursor: zoom-out;
}
}
/* Cursor zoom-in sur toutes les images */
img {
cursor: zoom-in;
}

View file

@ -652,6 +652,44 @@ section.poster-slider .controls button.poster-next {
transform: rotate(180deg);
}
/* Lightbox */
.lightbox {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.9);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
opacity: 0;
visibility: hidden;
transition: opacity 0.3s ease, visibility 0.3s ease;
}
.lightbox.open {
opacity: 1;
visibility: visible;
}
.lightbox__content {
display: flex;
justify-content: center;
align-items: center;
}
.lightbox__image {
width: 90vw;
height: 90vh;
-o-object-fit: contain;
object-fit: contain;
cursor: zoom-out;
}
/* Cursor zoom-in sur toutes les images */
img {
cursor: zoom-in;
}
@media screen and (max-width: 950px) {
:root {
--space-body: 1rem;

File diff suppressed because one or more lines are too long

View file

@ -14,5 +14,6 @@
@import 'src/sections/_video.scss';
@import 'src/sections/_timeline.scss';
@import 'src/sections/_poster-slider.scss';
@import 'src/_lightbox.scss';
@import 'src/_responsive.scss';

139
assets/js/lightbox.js Normal file
View file

@ -0,0 +1,139 @@
document.addEventListener('DOMContentLoaded', () => {
const lightbox = document.getElementById('lightbox');
const lightboxImg = document.querySelector('.lightbox__image');
let activeImg = null;
let startX = 0;
let startY = 0;
let startTime = 0;
const DRAG_THRESHOLD = 5;
const TAP_DURATION = 300; // ms
function openLightbox(imgSrc, imgAlt) {
lightboxImg.src = imgSrc;
lightboxImg.alt = imgAlt || 'Image en grand format';
lightbox.classList.add('open');
document.body.style.overflow = 'hidden';
}
function closeLightbox() {
lightbox.classList.remove('open');
document.body.style.overflow = '';
}
function handleStart(e, img) {
activeImg = img;
startTime = Date.now();
if (e.type === 'mousedown') {
startX = e.clientX;
startY = e.clientY;
} else if (e.type === 'touchstart') {
startX = e.touches[0].clientX;
startY = e.touches[0].clientY;
}
}
function handleMove(e) {
if (!activeImg) return;
let currentX, currentY;
if (e.type === 'mousemove') {
currentX = e.clientX;
currentY = e.clientY;
} else if (e.type === 'touchmove') {
currentX = e.touches[0].clientX;
currentY = e.touches[0].clientY;
} else {
return;
}
const dx = Math.abs(currentX - startX);
const dy = Math.abs(currentY - startY);
if (dx > DRAG_THRESHOLD || dy > DRAG_THRESHOLD) {
activeImg = null;
}
}
function handleEnd(e, img) {
if (!activeImg || activeImg !== img) return;
let currentX, currentY;
if (e.type === 'mouseup') {
currentX = e.clientX;
currentY = e.clientY;
} else if (e.type === 'touchend') {
currentX = e.changedTouches[0].clientX;
currentY = e.changedTouches[0].clientY;
} else {
return;
}
const dx = Math.abs(currentX - startX);
const dy = Math.abs(currentY - startY);
const duration = Date.now() - startTime;
// Ignorer si mouvement trop important ou durée trop longue
if (dx > DRAG_THRESHOLD || dy > DRAG_THRESHOLD || duration > TAP_DURATION) {
activeImg = null;
return;
}
// Vérifier si l'image est dans un slider Swiper
const swiperSlide = img.closest('.swiper-slide');
if (swiperSlide) {
const swiperContainer = swiperSlide.closest('.swiper');
if (swiperContainer && swiperContainer.swiper) {
const swiper = swiperContainer.swiper;
if (swiper.isDragging || swiper.isTouched || swiper.animating) {
activeImg = null;
return;
}
}
}
// Vérifier si le parent est un bouton ou lien
if (img.closest('button, a')) {
activeImg = null;
return;
}
openLightbox(img.src, img.alt);
activeImg = null;
if (e.type === 'touchend') {
e.preventDefault();
}
}
document.querySelectorAll('img').forEach(img => {
if (img.classList.contains('lightbox__image')) return;
// Mouse events
img.addEventListener('mousedown', (e) => handleStart(e, img), { passive: true });
img.addEventListener('mouseup', (e) => handleEnd(e, img));
// Touch events
img.addEventListener('touchstart', (e) => handleStart(e, img), { passive: true });
img.addEventListener('touchend', (e) => handleEnd(e, img), { passive: false });
});
// Global move listeners
document.addEventListener('mousemove', handleMove, { passive: true });
document.addEventListener('touchmove', handleMove, { passive: true });
// Reset on global up
document.addEventListener('mouseup', () => activeImg = null);
document.addEventListener('touchend', () => activeImg = null);
// Fermer la lightbox au clic n'importe ou dessus
lightbox.addEventListener('click', closeLightbox);
// Fermer avec Escape
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && lightbox.classList.contains('open')) {
closeLightbox();
}
});
});

View file

@ -16,6 +16,7 @@
defer
></script>
<script src="assets/js/poster-slider.js" defer></script>
<script src="assets/js/lightbox.js" defer></script>
<meta name="robots" content="none" />
</head>
<body>
@ -1341,5 +1342,13 @@
</ul>
</div>
</footer>
<!-- Lightbox -->
<div class="lightbox" id="lightbox">
<div class="lightbox__content">
<img src="" alt="Image en grand format" class="lightbox__image" />
</div>
</div>
</body>
</html>