# `Fresco`
[🔗](https://github.com/alexdont/fresco/blob/v0.8.0/lib/fresco.ex#L1)

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`](https://hex.pm/packages/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`.

# `canvas`

# `viewer`

---

*Consult [api-reference.md](api-reference.md) for complete listing*
