diff --git a/static/gallery.css b/static/gallery.css index 5c54c9f..5750671 100644 --- a/static/gallery.css +++ b/static/gallery.css @@ -40,7 +40,7 @@ font-size: 24px; color: #fff; cursor: pointer; - z-index: 10; + z-index: 100; background: transparent; border: none; padding: 0; diff --git a/static/gallery.js b/static/gallery.js index 32509e5..9315abd 100644 --- a/static/gallery.js +++ b/static/gallery.js @@ -1,3 +1,9 @@ +let isPinching = false; +let pinchZoomOccurred = false; +let initialPinchDistance = null; +let initialScale = 1; +let currentScale = 1; + // Assume that currentGalleryImages is already declared in app.js. // Only declare currentGalleryIndex if it isn't defined already. if (typeof currentGalleryIndex === "undefined") { @@ -46,6 +52,19 @@ function showGalleryImage(relUrl) { newImage.style.transition = 'opacity 0.5s ease-in-out'; newImage.style.opacity = 0; // Start fully transparent newImage.id = 'gallery-modal-content'; + + // Add pinch-to-zoom event listeners + newImage.addEventListener('touchstart', handlePinchStart, { passive: false }); + newImage.addEventListener('touchmove', handlePinchMove, { passive: false }); + newImage.addEventListener('touchend', handlePinchEnd, { passive: false }); + newImage.addEventListener('click', handleGalleryImageClick); + + + // Reset pinch variables for the new image + initialPinchDistance = null; + initialScale = 1; + currentScale = 1; + pinchZoomOccurred = false; // Append new image on top of existing ones modal.appendChild(newImage); @@ -100,21 +119,28 @@ function closeGalleryModal() { } function handleGalleryImageClick(e) { + // If a pinch zoom occurred, don't change the image. + if (pinchZoomOccurred) { + pinchZoomOccurred = false; // Reset the flag for the next gesture. + e.stopPropagation(); + return; + } + if (e.target.classList.contains('gallery-next') || e.target.classList.contains('gallery-prev')) { - return; // Prevent conflict + return; // Prevent conflict with navigation buttons. } const imgRect = this.getBoundingClientRect(); if (e.clientX < imgRect.left + imgRect.width / 2) { - if (currentGalleryIndex > 0) { - currentGalleryIndex--; - showGalleryImage(currentGalleryImages[currentGalleryIndex]); - } + if (currentGalleryIndex > 0) { + currentGalleryIndex--; + showGalleryImage(currentGalleryImages[currentGalleryIndex]); + } } else { - if (currentGalleryIndex < currentGalleryImages.length - 1) { - currentGalleryIndex++; - showGalleryImage(currentGalleryImages[currentGalleryIndex]); - } + if (currentGalleryIndex < currentGalleryImages.length - 1) { + currentGalleryIndex++; + showGalleryImage(currentGalleryImages[currentGalleryIndex]); + } } } @@ -127,10 +153,18 @@ function initGallerySwipe() { const galleryModal = document.getElementById('gallery-modal'); galleryModal.addEventListener('touchstart', function(e) { + // If more than one finger is on screen, ignore swipe tracking. + if (e.touches.length > 1) { + return; + } touchStartX = e.changedTouches[0].screenX; }, false); galleryModal.addEventListener('touchend', function(e) { + // If the event was part of a multi-touch (pinch) gesture or a pinch was detected, skip swipe. + if (e.changedTouches.length > 1 || isPinching || pinchZoomOccurred) { + return; + } touchEndX = e.changedTouches[0].screenX; handleSwipe(); }, false); @@ -153,6 +187,41 @@ function initGallerySwipe() { } } +function handlePinchStart(e) { + if (e.touches.length === 2) { + e.preventDefault(); + isPinching = true; + pinchZoomOccurred = false; // Reset at the start of a pinch gesture. + const dx = e.touches[0].pageX - e.touches[1].pageX; + const dy = e.touches[0].pageY - e.touches[1].pageY; + initialPinchDistance = Math.sqrt(dx * dx + dy * dy); + } +} + +function handlePinchMove(e) { + if (e.touches.length === 2 && initialPinchDistance) { + e.preventDefault(); + const dx = e.touches[0].pageX - e.touches[1].pageX; + const dy = e.touches[0].pageY - e.touches[1].pageY; + const currentDistance = Math.sqrt(dx * dx + dy * dy); + let scale = currentDistance / initialPinchDistance; + scale = Math.max(0.5, Math.min(scale * initialScale, 3)); + // If the scale has changed enough, mark that a pinch zoom occurred. + if (Math.abs(scale - initialScale) > 0.05) { + pinchZoomOccurred = true; + } + currentScale = scale; + e.currentTarget.style.transform = `translate(-50%, -50%) scale(${scale})`; + } +} + +function handlePinchEnd(e) { + if (e.touches.length < 2) { + initialScale = currentScale; + initialPinchDistance = null; + isPinching = false; + } +} @@ -186,10 +255,7 @@ function initGalleryControls() { function initGallery() { - const galleryImage = document.getElementById('gallery-modal-content'); - if (galleryImage) { - galleryImage.addEventListener('click', handleGalleryImageClick); - } + initGallerySwipe(); initGalleryControls(); diff --git a/templates/app.html b/templates/app.html index 82f0dc6..f2df4d3 100644 --- a/templates/app.html +++ b/templates/app.html @@ -90,10 +90,10 @@