From 6e33f17cba2c6deedd7584cbd5604ed6544430d1 Mon Sep 17 00:00:00 2001 From: Xin Date: Thu, 11 Sep 2025 20:52:59 +0100 Subject: [PATCH] feat(image-zoom): implement multi-touch pinch detection for zoom functionality - Added support for pinch gestures to enhance the zoom experience on touch devices. - Implemented event listeners for pointer events to manage pinch start and end. - Updated closing behavior to account for active pinch gestures, improving user interaction. --- assets/js/image-zoom.js | 45 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/assets/js/image-zoom.js b/assets/js/image-zoom.js index 783d362..31ff481 100644 --- a/assets/js/image-zoom.js +++ b/assets/js/image-zoom.js @@ -23,12 +23,42 @@ overlay.appendChild(img); + // Track pinch gesture + let pinching = false; + let pinchTimer = 0; + const activeTouchPointers = new Set(); + function pinchingStart() { + pinching = true; + if (pinchTimer) clearTimeout(pinchTimer); + } + function pinchingEndSoon() { + if (pinchTimer) clearTimeout(pinchTimer); + pinchTimer = setTimeout(() => (pinching = false), 350); + } + function onPointerDown(e) { + if (e.pointerType === 'touch') { + activeTouchPointers.add(e.pointerId); + if (activeTouchPointers.size > 1) pinchingStart(); + } + } + function onPointerUp(e) { + if (e.pointerType === 'touch') { + activeTouchPointers.delete(e.pointerId); + if (activeTouchPointers.size < 2) pinchingEndSoon(); + } + } + function close(immediate = false) { // trigger dedicated closing transitions for smoother zoom-out overlay.classList.add("closing"); window.removeEventListener("keydown", onKeyDown, true); window.removeEventListener("scroll", onScroll, true); overlay.removeEventListener("wheel", onWheel); + overlay.removeEventListener("pointerdown", onPointerDown); + overlay.removeEventListener("pointerup", onPointerUp); + overlay.removeEventListener("pointercancel", onPointerUp); + activeTouchPointers.clear(); + if (pinchTimer) clearTimeout(pinchTimer); if (immediate) { overlay.remove(); @@ -44,10 +74,21 @@ overlay.addEventListener("click", () => close(false), { once: true }); window.addEventListener("keydown", onKeyDown, true); - function onWheel(e) { if (e && e.ctrlKey) return; close(true); } - function onScroll() { close(true); } + function onWheel(e) { + // Ignore trackpad pinch (wheel + ctrlKey) and active pinch + if ((e && e.ctrlKey) || pinching) return; + close(true); + } + function onScroll() { + if (pinching) return; + close(true); + } overlay.addEventListener("wheel", onWheel, { passive: true }); + // Standard W3C pointer events for multi-touch pinch detection + overlay.addEventListener("pointerdown", onPointerDown); + overlay.addEventListener("pointerup", onPointerUp); + overlay.addEventListener("pointercancel", onPointerUp); window.addEventListener("scroll", onScroll, true); document.body.appendChild(overlay);