Skip to content

v0.3.0

tagged this 17 May 19:44
Opt-in viewer mode tuned for long-scroll reading content (manhwa,
manga, comics, document viewers) where the user pans continuously
and rarely zooms. By default OSD repaints the canvas via
ctx.drawImage(tile) every pan frame — fine on desktop, painfully
slow on iOS Safari even on recent hardware. The new
`:pan_optimized` attr swaps that per-frame redraw for a GPU-
composited `transform: translate3d` glide during the gesture,
dropping per-frame cost from ~10-20ms to <1ms.

Mechanism (JS hook):

- On pan-start, the hook saves OSD's drawer.draw, replaces it with
  a no-op, and emits `fast-pan {phase:"start"}` through the
  existing handle.on subscriber list (via a new `handle._emit`
  internal method).
- Per pan tick, computes the screen-pixel delta of the original
  viewport center using `viewport.pixelFromPoint(startCenter,true)`
  and applies `transform: translate3d(dx, dy, 0)` to the canvas.
  Emits `fast-pan {phase:"delta", x:dx, y:dy}`.
- On animation-finish (or zoom-change / overscan bail), restores
  drawer.draw, clears the canvas transform, triggers one immediate
  repaint at the committed position, and emits
  `fast-pan {phase:"end"}`.

The fast path bails to OSD's normal redraw on zoom mid-pan, when
cumulative delta crosses 50% of viewport height (overscan), or
when `:rotate` is active (rotation invalidates simple translate
math).

A new `fast-pan` event in the handle.on channel lets overlay
extensions transform in lockstep. Etcher >= 0.2.8 listens
automatically — its SVG overlay wrapper picks up the same
translate3d so annotations stay anchored. Older Etcher paired
with :pan_optimized would see annotations drift visibly during
the pan window (documented in the new README section + CHANGELOG
notes).

Bumped to minor because the release adds a new public attr and
a new synthetic event channel that creates a coordination
contract with overlay libraries. No breaking changes; default off
for `:pan_optimized` means existing viewers see no behavior change.

- `lib/fresco/viewer.ex`: new `:pan_optimized` attr (defaults
  false), plumbed to `data-pan-optimized` on the host.
- `priv/static/fresco.js`: new `installFastPan` module + new
  `handle._emit` internal method; module header updated with the
  fast-pan event description.
- `test/fresco_test.exs`: 2 new render-assertion tests (default
  off, opt-in true).
- `README.md`: new "Optimized pan for long-scroll content" section
  with the consumer API and the overlay-coordination contract.
- `CHANGELOG.md`: 0.3.0 entry.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Assets 2
Loading