Spaces:
Sleeping
Sleeping
Apply zoom styles only when actively zoomed (preserves Gradio centering)
Browse files
app.py
CHANGED
|
@@ -300,24 +300,31 @@ def choose(side: str, session: dict):
|
|
| 300 |
# Shift+wheel zoom, drag-pan when zoomed, dbl-click reset. Pan is clamped so
|
| 301 |
# the image always fills its container; max 4x. Resets on src change.
|
| 302 |
ZOOM_HEAD = """
|
| 303 |
-
<style>
|
| 304 |
-
.zoomable img {
|
| 305 |
-
transform-origin: 0 0;
|
| 306 |
-
transition: transform 0.05s ease-out;
|
| 307 |
-
will-change: transform;
|
| 308 |
-
}
|
| 309 |
-
</style>
|
| 310 |
<script>
|
| 311 |
(function () {
|
| 312 |
const MAX_SCALE = 10;
|
| 313 |
function bind(img) {
|
| 314 |
if (img.__zoomBound) return;
|
| 315 |
img.__zoomBound = true;
|
| 316 |
-
// Clip on the immediate parent only; broader CSS selectors collapse
|
| 317 |
-
// Gradio's column layout for the A/B images.
|
| 318 |
-
if (img.parentElement) img.parentElement.style.overflow = 'hidden';
|
| 319 |
let scale = 1, tx = 0, ty = 0;
|
| 320 |
let dragging = false, lastX = 0, lastY = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 321 |
function clamp() {
|
| 322 |
const w = img.clientWidth || img.naturalWidth || 1;
|
| 323 |
const h = img.clientHeight || img.naturalHeight || 1;
|
|
@@ -325,10 +332,14 @@ ZOOM_HEAD = """
|
|
| 325 |
tx = Math.min(0, Math.max(minX, tx));
|
| 326 |
ty = Math.min(0, Math.max(minY, ty));
|
| 327 |
}
|
| 328 |
-
const apply = () => {
|
| 329 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 330 |
img.addEventListener('wheel', (e) => {
|
| 331 |
-
if (!e.shiftKey) return;
|
| 332 |
e.preventDefault();
|
| 333 |
const factor = e.deltaY < 0 ? 1.15 : 1 / 1.15;
|
| 334 |
const ns = Math.min(MAX_SCALE, Math.max(1, scale * factor));
|
|
|
|
| 300 |
# Shift+wheel zoom, drag-pan when zoomed, dbl-click reset. Pan is clamped so
|
| 301 |
# the image always fills its container; max 4x. Resets on src change.
|
| 302 |
ZOOM_HEAD = """
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 303 |
<script>
|
| 304 |
(function () {
|
| 305 |
const MAX_SCALE = 10;
|
| 306 |
function bind(img) {
|
| 307 |
if (img.__zoomBound) return;
|
| 308 |
img.__zoomBound = true;
|
|
|
|
|
|
|
|
|
|
| 309 |
let scale = 1, tx = 0, ty = 0;
|
| 310 |
let dragging = false, lastX = 0, lastY = 0;
|
| 311 |
+
const parent = img.parentElement;
|
| 312 |
+
|
| 313 |
+
// Apply zoom styles only while actively zoomed; restoring them on reset
|
| 314 |
+
// lets Gradio's own positioning/centering work at scale=1.
|
| 315 |
+
function setZoomStyles(on) {
|
| 316 |
+
if (!parent) return;
|
| 317 |
+
if (on) {
|
| 318 |
+
parent.style.overflow = 'hidden';
|
| 319 |
+
img.style.transformOrigin = '0 0';
|
| 320 |
+
img.style.willChange = 'transform';
|
| 321 |
+
} else {
|
| 322 |
+
parent.style.overflow = '';
|
| 323 |
+
img.style.transformOrigin = '';
|
| 324 |
+
img.style.willChange = '';
|
| 325 |
+
img.style.transform = '';
|
| 326 |
+
}
|
| 327 |
+
}
|
| 328 |
function clamp() {
|
| 329 |
const w = img.clientWidth || img.naturalWidth || 1;
|
| 330 |
const h = img.clientHeight || img.naturalHeight || 1;
|
|
|
|
| 332 |
tx = Math.min(0, Math.max(minX, tx));
|
| 333 |
ty = Math.min(0, Math.max(minY, ty));
|
| 334 |
}
|
| 335 |
+
const apply = () => {
|
| 336 |
+
setZoomStyles(true);
|
| 337 |
+
clamp();
|
| 338 |
+
img.style.transform = `translate(${tx}px, ${ty}px) scale(${scale})`;
|
| 339 |
+
};
|
| 340 |
+
const reset = () => { scale = 1; tx = 0; ty = 0; setZoomStyles(false); };
|
| 341 |
img.addEventListener('wheel', (e) => {
|
| 342 |
+
if (!e.shiftKey) return;
|
| 343 |
e.preventDefault();
|
| 344 |
const factor = e.deltaY < 0 ? 1.15 : 1 / 1.15;
|
| 345 |
const ns = Math.min(MAX_SCALE, Math.max(1, scale * factor));
|