From f1f056f7f3866b4e8dabe4a0bdc36f45bc2a7851 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20FAMIBELLE-PRONZOLA?= Date: Wed, 8 Oct 2025 20:50:52 +0400 Subject: [PATCH] fix: adapt carousel control on mobile --- css/styles.css | 13 +++++ js/main.js | 143 ++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 144 insertions(+), 12 deletions(-) diff --git a/css/styles.css b/css/styles.css index 9ba754d..c183b84 100644 --- a/css/styles.css +++ b/css/styles.css @@ -1207,6 +1207,12 @@ img { display: flex; transition: transform 0.5s ease; padding-bottom: 10px; + cursor: grab; + user-select: none; +} + +.carousel-container:active { + cursor: grabbing; } .carousel-item { @@ -1215,6 +1221,13 @@ img { margin-right: 20px; } +/* Réduire l'espacement en mobile */ +@media (max-width: 768px) { + .carousel-item { + margin-right: 10px; + } +} + .carousel-controls { display: flex; justify-content: center; diff --git a/js/main.js b/js/main.js index 077499b..c8c9ff2 100644 --- a/js/main.js +++ b/js/main.js @@ -116,27 +116,146 @@ document.addEventListener('DOMContentLoaded', function() { // Gestion des carousels const carousels = document.querySelectorAll('.carousel'); - + carousels.forEach(carousel => { const container = carousel.querySelector('.carousel-container'); const dots = carousel.querySelectorAll('.carousel-dot'); const items = carousel.querySelectorAll('.carousel-item'); - + if (dots.length > 0 && items.length > 0) { + let currentIndex = 0; + let startX = 0; + let currentX = 0; + let isDragging = false; + let startTransform = 0; + + function getItemWidth() { + return items[0].offsetWidth + parseInt(getComputedStyle(items[0]).marginRight); + } + + function updateCarousel(index) { + const itemWidth = getItemWidth(); + const newTransform = -index * itemWidth; + container.style.transform = `translateX(${newTransform}px)`; + + // Mettre à jour les dots + dots.forEach(d => d.classList.remove('active')); + if (dots[index]) { + dots[index].classList.add('active'); + } + + currentIndex = index; + } + dots.forEach((dot, index) => { dot.addEventListener('click', function() { - // Calculer la distance à translater - const itemWidth = items[0].offsetWidth + parseInt(getComputedStyle(items[0]).marginRight); - const newTransform = -index * itemWidth; - - // Appliquer la transformation - container.style.transform = `translateX(${newTransform}px)`; - - // Mettre à jour les dots - dots.forEach(d => d.classList.remove('active')); - dot.classList.add('active'); + updateCarousel(index); }); }); + + container.addEventListener('touchstart', function(e) { + isDragging = true; + startX = e.touches[0].clientX; + const transform = window.getComputedStyle(container).transform; + + if (transform !== 'none') { + const matrix = new DOMMatrix(transform); + startTransform = matrix.m41; + } else { + startTransform = 0; + } + container.style.transition = 'none'; + }, { passive: true }); + + container.addEventListener('touchmove', function(e) { + if (!isDragging) return; + + currentX = e.touches[0].clientX; + const diff = currentX - startX; + const newTransform = startTransform + diff; + + container.style.transform = `translateX(${newTransform}px)`; + }, { passive: true }); + + container.addEventListener('touchend', function(e) { + if (!isDragging) return; + isDragging = false; + + container.style.transition = 'transform 0.5s ease'; + + const diff = currentX - startX; + const threshold = 50; // Distance minimale pour considérer un swipe + + // Déterminer la direction du swipe + if (Math.abs(diff) > threshold) { + if (diff > 0 && currentIndex > 0) { + // Swipe vers la droite - item précédent + updateCarousel(currentIndex - 1); + } else if (diff < 0 && currentIndex < items.length - 1) { + // Swipe vers la gauche - item suivant + updateCarousel(currentIndex + 1); + } else { + // Retour à la position actuelle + updateCarousel(currentIndex); + } + } else { + // Mouvement trop petit, retour à la position actuelle + updateCarousel(currentIndex); + } + + currentX = 0; + }, { passive: true }); + + // Support du drag sur desktop (optionnel) + container.addEventListener('mousedown', function(e) { + isDragging = true; + startX = e.clientX; + const transform = window.getComputedStyle(container).transform; + if (transform !== 'none') { + const matrix = new DOMMatrix(transform); + startTransform = matrix.m41; + } else { + startTransform = 0; + } + container.style.transition = 'none'; + container.style.cursor = 'grabbing'; + e.preventDefault(); + }); + + document.addEventListener('mousemove', function(e) { + if (!isDragging) return; + + currentX = e.clientX; + const diff = currentX - startX; + const newTransform = startTransform + diff; + + container.style.transform = `translateX(${newTransform}px)`; + }); + + document.addEventListener('mouseup', function(e) { + if (!isDragging) return; + isDragging = false; + + container.style.transition = 'transform 0.5s ease'; + container.style.cursor = 'grab'; + + const diff = currentX - startX; + const threshold = 50; + + if (Math.abs(diff) > threshold) { + if (diff > 0 && currentIndex > 0) { + updateCarousel(currentIndex - 1); + } else if (diff < 0 && currentIndex < items.length - 1) { + updateCarousel(currentIndex + 1); + } else { + updateCarousel(currentIndex); + } + } else { + updateCarousel(currentIndex); + } + + currentX = 0; + }); } });