aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/app.js10
1 files changed, 10 insertions, 0 deletions
diff --git a/src/app.js b/src/app.js
index 2bc7a39..6513356 100644
--- a/src/app.js
+++ b/src/app.js
@@ -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) => {