diff options
| -rw-r--r-- | src/app.js | 10 |
1 files changed, 10 insertions, 0 deletions
@@ -648,12 +648,22 @@ function attachZoom(box, img, { wheel = true } = {}) { const mx = Math.max(0, (img.offsetWidth * s - window.innerWidth) / 2), my = Math.max(0, (img.offsetHeight * s - window.innerHeight) / 2); x = Math.min(mx, Math.max(-mx, x)); y = Math.min(my, Math.max(-my, y)); }; + // Chrome keeps a will-change: transform layer rastered at 1× and scales + // the bitmap: zoomed in, the raster's tiles show as a faint grid of + // seams across the picture ("very faint grid lines", Adam, 2026-11-02). + // The hint is on while a gesture moves the picture (no re-raster per + // frame) and off once it settles zoomed, so the picture is drawn again + // at its real scale: sharp, and seamless. + let settle = 0; const apply = (animate) => { + clearTimeout(settle); img.style.transition = animate ? 'transform .2s ease' : 'none'; img.style.transform = s === 1 && !x && !y ? '' : `translate(${x}px, ${y}px) scale(${s})`; img.style.cursor = s > 1 ? 'grab' : ''; // zoomed, the finger pans the picture; at 1× the touch is the page's (a pager's swipe) img.style.touchAction = s > 1 ? 'none' : ''; + img.style.willChange = 'transform'; + settle = setTimeout(() => { img.style.willChange = s > 1 ? 'auto' : ''; }, animate ? 250 : 120); }; // scale to ns keeping the picture point under (cx, cy) where it is const zoomAt = (ns, cx, cy) => { |
