Fresco (fresco v0.6.0)

Copy Markdown View Source

Fresco is a polished pan-zoom image viewer for Phoenix apps.

The metaphor: a fresco is the wet-plaster surface you paint on. Fresco the library is the surface every layered image experience sits on top of — annotation tools, ML overlays, measurement widgets, and so on. They attach to the same Fresco viewer instance through a small extension registry.

Used on its own, Fresco is a complete viewer: pan, zoom (wheel, pinch, buttons, keyboard), fit-to-view, fullscreen, Heroicons nav overlay, smooth gestures on mobile.

Used as a host for extensions, Fresco exposes a coordinate adapter, event pub/sub, and a small extension registry so peer libraries can attach by DOM id without needing to fork the viewer.

Quick start

<Fresco.viewer
  id="photo"
  src={~p"/uploads/photo.jpg"}
  class="w-full h-[80vh] rounded"
/>

Extending

Extensions look up the live viewer handle by DOM id:

// In another LiveView hook on the same page:
window.Fresco.onViewerReady("photo", function(handle) {
  handle.on("zoom", function(e) { /*  */ });
  handle.swapSourcePreservingBounds("/path/to/different-source");
});

Annotation-style overlays can also attach as children of the .fresco-stage element to inherit the transform automatically — no per-frame coordinate math required for the common case.

Source providers transform a URL into a Fresco tile source:

window.Fresco.registerSourceProvider(
  function(url) { return url.endsWith(".my-format"); },
  function(url) { return { type: "image", url: rewrite(url) }; }
);

See Fresco.Viewer and Fresco.Canvas for the per-component references. Vertical-scroll strip mode lives in the separate fresco_strip package (extracted in fresco 0.6.0) so consumers who only need the viewer / canvas surface stay lightweight.

Two component shapes

  • <Fresco.viewer> — pan/zoom for a single image. Hand-rolled CSS-transform engine; native Pointer Events; smooth on iOS Safari. Use when the user is panning around a single image and may want to zoom in.
  • <Fresco.canvas> — N images laid out at absolute canvas-pixel coordinates on a virtual canvas, plus an open extensions map for annotation tools / overlays. Serializes to a single .fresco JSON file so an entire scene lives in one place instead of scattered DB tables. Single-image is just the N=1 case. Use when the user is building a layered scene they'll save.

For vertical-scroll-strip reading (manhwa, long-form web comics, IG-style feeds), reach for FrescoStrip.viewer from fresco_strip. Both packages contribute handles to the same window.Fresco registry so peer libraries (Etcher annotations, ML overlays, comment threads) work uniformly across them.

Both shapes share the registry — window.Fresco.onReady(domId, callback) works for either, and the handle each yields exposes a partly-shared surface (container, on, appendNavButton) plus its own kind-specific methods (viewer: imageToScreen / fitBounds; canvas: same plus getImages / imageBoundsFor / fitImage / getExtension). Feature-detect with "getImages" in handle (canvas) or assume viewer otherwise. For strip, use "scrollTo" in handle.

Summary

Functions

canvas(assigns)

See Fresco.Canvas.canvas/1.

viewer(assigns)

See Fresco.Viewer.viewer/1.