Add swipe and keyboard navigation to the pure image zoom overlay
Arrow keys and touch swipe now navigate between plates while the zoom is open, keeping the lightbox in sync underneath. goToZoomSlide clamps to list bounds and delegates to goToSlide for thumb/index sync. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+22
-2
@@ -212,6 +212,7 @@
|
||||
let lbBuilt = false;
|
||||
let lbReferrer = null; // URL to return to on close
|
||||
let imgZoomOpen = false;
|
||||
let imgZoomIdx = -1;
|
||||
|
||||
function lbOpen(slug, scopedList) {
|
||||
lbList = scopedList || POSTS;
|
||||
@@ -350,8 +351,8 @@
|
||||
document.addEventListener('keydown', e => {
|
||||
if (lb.dataset.open !== 'true') return;
|
||||
if (e.key === 'Escape') { if (imgZoomOpen) closeImgZoom(); else lbClose(); }
|
||||
if (e.key === 'ArrowLeft') { e.preventDefault(); goToSlide(lbIdx - 1); }
|
||||
if (e.key === 'ArrowRight') { e.preventDefault(); goToSlide(lbIdx + 1); }
|
||||
if (e.key === 'ArrowLeft') { e.preventDefault(); imgZoomOpen ? goToZoomSlide(imgZoomIdx - 1) : goToSlide(lbIdx - 1); }
|
||||
if (e.key === 'ArrowRight') { e.preventDefault(); imgZoomOpen ? goToZoomSlide(imgZoomIdx + 1) : goToSlide(lbIdx + 1); }
|
||||
});
|
||||
|
||||
// Touch swipe
|
||||
@@ -477,6 +478,7 @@
|
||||
function openImgZoom(src) {
|
||||
if (!imgZoom || !imgZoomImg || !src) return;
|
||||
imgZoomImg.src = src;
|
||||
imgZoomIdx = lbIdx;
|
||||
imgZoom.dataset.open = 'true';
|
||||
imgZoomOpen = true;
|
||||
document.body.style.overflow = 'hidden';
|
||||
@@ -489,6 +491,14 @@
|
||||
if (!lb || lb.dataset.open !== 'true') document.body.style.overflow = '';
|
||||
}
|
||||
|
||||
function goToZoomSlide(idx) {
|
||||
if (!lbList.length || !imgZoomImg) return;
|
||||
imgZoomIdx = Math.max(0, Math.min(idx, lbList.length - 1));
|
||||
const p = lbList[imgZoomIdx];
|
||||
if (p) imgZoomImg.src = p.card || p.thumb || '';
|
||||
goToSlide(imgZoomIdx);
|
||||
}
|
||||
|
||||
// Hero "View full image" button
|
||||
const viewFullBtn = document.getElementById('viewFull');
|
||||
if (viewFullBtn) {
|
||||
@@ -505,6 +515,16 @@
|
||||
if (imgZoom) {
|
||||
imgZoom.addEventListener('click', e => { if (e.target === imgZoom) closeImgZoom(); });
|
||||
document.getElementById('imgZoomClose')?.addEventListener('click', closeImgZoom);
|
||||
|
||||
// Swipe to navigate
|
||||
let zoomTouchX = null;
|
||||
imgZoom.addEventListener('touchstart', e => { zoomTouchX = e.touches[0].clientX; }, { passive: true });
|
||||
imgZoom.addEventListener('touchend', e => {
|
||||
if (zoomTouchX === null) return;
|
||||
const dx = e.changedTouches[0].clientX - zoomTouchX;
|
||||
if (Math.abs(dx) > 50) dx < 0 ? goToZoomSlide(imgZoomIdx + 1) : goToZoomSlide(imgZoomIdx - 1);
|
||||
zoomTouchX = null;
|
||||
});
|
||||
}
|
||||
|
||||
// Escape when lightbox is NOT open (standalone zoom)
|
||||
|
||||
Reference in New Issue
Block a user