Spaces:
Sleeping
Sleeping
Tame zoom: shift+wheel, max 4x, clamp pan
Browse files
app.py
CHANGED
|
@@ -297,8 +297,8 @@ def choose(side: str, session: dict):
|
|
| 297 |
|
| 298 |
# ---------- UI ----------------------------------------------------------------
|
| 299 |
|
| 300 |
-
#
|
| 301 |
-
#
|
| 302 |
ZOOM_HEAD = """
|
| 303 |
<style>
|
| 304 |
.zoomable [data-testid="image"], .zoomable .image-frame, .zoomable .image-container {
|
|
@@ -312,17 +312,26 @@ ZOOM_HEAD = """
|
|
| 312 |
</style>
|
| 313 |
<script>
|
| 314 |
(function () {
|
|
|
|
| 315 |
function bind(img) {
|
| 316 |
if (img.__zoomBound) return;
|
| 317 |
img.__zoomBound = true;
|
| 318 |
let scale = 1, tx = 0, ty = 0;
|
| 319 |
let dragging = false, lastX = 0, lastY = 0;
|
| 320 |
-
|
| 321 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 322 |
img.addEventListener('wheel', (e) => {
|
|
|
|
| 323 |
e.preventDefault();
|
| 324 |
-
const factor = e.deltaY < 0 ? 1.
|
| 325 |
-
const ns = Math.min(
|
| 326 |
if (ns === scale) return;
|
| 327 |
const rect = img.getBoundingClientRect();
|
| 328 |
const ox = e.clientX - rect.left;
|
|
@@ -370,7 +379,7 @@ with gr.Blocks(title="Denoising A/B Judging", theme=gr.themes.Soft(), head=ZOOM_
|
|
| 370 |
"denoised versions of it below, labelled **A** and **B**. The two "
|
| 371 |
"versions come from different denoising approaches, presented in a "
|
| 372 |
"random left/right order so the comparison stays blind. "
|
| 373 |
-
"
|
| 374 |
"**Which denoised image would you rather work with?**"
|
| 375 |
)
|
| 376 |
|
|
|
|
| 297 |
|
| 298 |
# ---------- UI ----------------------------------------------------------------
|
| 299 |
|
| 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 [data-testid="image"], .zoomable .image-frame, .zoomable .image-container {
|
|
|
|
| 312 |
</style>
|
| 313 |
<script>
|
| 314 |
(function () {
|
| 315 |
+
const MAX_SCALE = 4;
|
| 316 |
function bind(img) {
|
| 317 |
if (img.__zoomBound) return;
|
| 318 |
img.__zoomBound = true;
|
| 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;
|
| 324 |
+
const minX = w - w * scale, minY = h - h * scale;
|
| 325 |
+
tx = Math.min(0, Math.max(minX, tx));
|
| 326 |
+
ty = Math.min(0, Math.max(minY, ty));
|
| 327 |
+
}
|
| 328 |
+
const apply = () => { clamp(); img.style.transform = `translate(${tx}px, ${ty}px) scale(${scale})`; };
|
| 329 |
+
const reset = () => { scale = 1; tx = 0; ty = 0; img.style.transform = ''; };
|
| 330 |
img.addEventListener('wheel', (e) => {
|
| 331 |
+
if (!e.shiftKey) return; // plain scroll = page scroll
|
| 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));
|
| 335 |
if (ns === scale) return;
|
| 336 |
const rect = img.getBoundingClientRect();
|
| 337 |
const ox = e.clientX - rect.left;
|
|
|
|
| 379 |
"denoised versions of it below, labelled **A** and **B**. The two "
|
| 380 |
"versions come from different denoising approaches, presented in a "
|
| 381 |
"random left/right order so the comparison stays blind. "
|
| 382 |
+
"Hold **Shift** and scroll over an image to zoom (up to 4×), drag to pan, double-click to reset.\n\n"
|
| 383 |
"**Which denoised image would you rather work with?**"
|
| 384 |
)
|
| 385 |
|