From 07a5c3baf999f949130e61b65fe80360096f6d82 Mon Sep 17 00:00:00 2001 From: Franzz Date: Tue, 5 May 2026 20:54:04 +0200 Subject: [PATCH] Fix lightbox zooming --- src/scripts/lightbox.js | 74 +++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 28 deletions(-) diff --git a/src/scripts/lightbox.js b/src/scripts/lightbox.js index d094633..5e9fec2 100644 --- a/src/scripts/lightbox.js +++ b/src/scripts/lightbox.js @@ -468,26 +468,24 @@ export default class Lightbox { event.preventDefault(); const rect = this.image.getBoundingClientRect(); - const oldZoom = parseFloat(this.image.style.getPropertyValue('--scale') || '1'); - const oldTranslateX = parseFloat(this.image.style.getPropertyValue('--translate-x') || '0'); - const oldTranslateY = parseFloat(this.image.style.getPropertyValue('--translate-y') || '0'); + const oldTransform = this.getImageTransform(); + const oldZoom = oldTransform.scale; const maxZoom = Math.max(media.width / Math.max(this.image.width, 1), media.height / Math.max(this.image.height, 1), 1); const newZoom = Math.min(Math.max(oldZoom + (-Math.sign(event.deltaY) / 10), 1), maxZoom); - const offsetX = event.clientX - rect.left; - const offsetY = event.clientY - rect.top; - let translateX = oldTranslateX + (newZoom - oldZoom) * ((this.image.width / 2) - offsetX); - let translateY = oldTranslateY + (newZoom - oldZoom) * ((this.image.height / 2) - offsetY); - const maxTranslateX = (newZoom - 1) * this.image.width / 2; - const maxTranslateY = (newZoom - 1) * this.image.height / 2; - - translateX = Math.max(Math.min(translateX, maxTranslateX), -maxTranslateX); - translateY = Math.max(Math.min(translateY, maxTranslateY), -maxTranslateY); + const imageCenterX = rect.left + rect.width / 2 - oldTransform.translateX; + const imageCenterY = rect.top + rect.height / 2 - oldTransform.translateY; + const cursorX = event.clientX - imageCenterX; + const cursorY = event.clientY - imageCenterY; + const zoomRatio = newZoom / oldZoom; + const transform = this.clampImageTransform({ + scale: newZoom, + translateX: cursorX - zoomRatio * (cursorX - oldTransform.translateX), + translateY: cursorY - zoomRatio * (cursorY - oldTransform.translateY) + }); this.container.classList.toggle('moveable', newZoom > 1); - this.image.style.setProperty('--scale', String(newZoom)); - this.image.style.setProperty('--translate-x', `${translateX}px`); - this.image.style.setProperty('--translate-y', `${translateY}px`); + this.setImageTransform(transform); } onDragStart(event) { @@ -502,16 +500,13 @@ export default class Lightbox { onDragMove(event) { const zoom = parseFloat(this.image.style.getPropertyValue('--scale') || '1'); - let translateX = event.clientX - this.gMouseDownOffsetX; - let translateY = event.clientY - this.gMouseDownOffsetY; - const maxTranslateX = (zoom - 1) * this.image.width / 2; - const maxTranslateY = (zoom - 1) * this.image.height / 2; + const transform = this.clampImageTransform({ + scale: zoom, + translateX: event.clientX - this.gMouseDownOffsetX, + translateY: event.clientY - this.gMouseDownOffsetY + }); - translateX = Math.max(Math.min(translateX, maxTranslateX), -maxTranslateX); - translateY = Math.max(Math.min(translateY, maxTranslateY), -maxTranslateY); - - this.image.style.setProperty('--translate-x', `${translateX}px`); - this.image.style.setProperty('--translate-y', `${translateY}px`); + this.setImageTransform(transform); } onDragEnd() { @@ -520,9 +515,32 @@ export default class Lightbox { } resetImageTransform() { - this.image.style.setProperty('--scale', '1'); - this.image.style.setProperty('--translate-x', '0px'); - this.image.style.setProperty('--translate-y', '0px'); + this.setImageTransform({scale: 1, translateX: 0, translateY: 0}); + } + + getImageTransform() { + return { + scale: parseFloat(this.image.style.getPropertyValue('--scale') || '1'), + translateX: parseFloat(this.image.style.getPropertyValue('--translate-x') || '0'), + translateY: parseFloat(this.image.style.getPropertyValue('--translate-y') || '0') + }; + } + + clampImageTransform(transform) { + const maxTranslateX = (transform.scale - 1) * this.image.width / 2; + const maxTranslateY = (transform.scale - 1) * this.image.height / 2; + + return { + scale: transform.scale, + translateX: Math.max(Math.min(transform.translateX, maxTranslateX), -maxTranslateX), + translateY: Math.max(Math.min(transform.translateY, maxTranslateY), -maxTranslateY) + }; + } + + setImageTransform(transform) { + this.image.style.setProperty('--scale', String(transform.scale)); + this.image.style.setProperty('--translate-x', `${transform.translateX}px`); + this.image.style.setProperty('--translate-y', `${transform.translateY}px`); } hideElements(elements) { @@ -573,4 +591,4 @@ export default class Lightbox { if (this.options.disableScrolling) document.body.classList.remove('lb-disable-scrolling'); this.options.onClosing(); } -} \ No newline at end of file +}