Phoenix LiveView function component that mounts an OpenSeadragon viewer with progressive multi-layer zoom.
The component accepts an ordered list of sources (low → high quality)
and switches between them as the user zooms. Each layer covers the
zoom band where its native resolution is roughly 1:1 with the rendered
pixels; beyond that, the next layer up takes over. Layers are tagged
with their intrinsic pixel width so the client can compute
thresholds; layers without a width (typically a .dzi manifest) are
treated as the top layer with infinite zoom headroom.
The component renders a <div> with phx-hook="TesseraViewer". The
client-side hook (defined in priv/static/tessera.js) lazy-loads
OpenSeadragon from jsDelivr on first mount, opens the first source,
then upgrades / downgrades the source as zoom crosses each layer's
threshold.
Usage
Two-layer (medium → DZI):
<Tessera.viewer
id="photo"
sources={[
%{url: ~p"/uploads/photo-medium.jpg", width: 1024},
%{url: ~p"/dzi/photo.dzi"}
]}
class="w-full h-[80vh] rounded"
/>Three-layer (medium → large → DZI), useful for 4K+ images:
<Tessera.viewer
id="photo"
sources={[
%{url: ~p"/uploads/photo-medium.jpg", width: 1024},
%{url: ~p"/uploads/photo-large.jpg", width: 2560},
%{url: ~p"/dzi/photo.dzi"}
]}
class="w-full h-[80vh] rounded"
/>Plain pan + zoom on a single image:
<Tessera.viewer
id="thumb"
sources={[%{url: ~p"/uploads/photo.jpg"}]}
class="w-full h-96"
/>Source detection
Each source's URL extension is sniffed at the JS layer. .dzi →
OpenSeadragon's DZI tile source; anything else → OSD's built-in
"simple image" tile source. Pan and zoom work either way; deep zoom
with progressive tile loading only kicks in for DZI sources.
Parent app setup
Import tessera.js in the parent's app.js and spread TesseraHooks
into the LiveSocket hooks:
import "../../deps/tessera/priv/static/tessera.js"
let liveSocket = new LiveSocket("/live", Socket, {
hooks: { ...window.TesseraHooks, ...colocatedHooks }
})
Summary
Functions
Renders an OpenSeadragon viewer with progressive multi-layer zoom.
Functions
Renders an OpenSeadragon viewer with progressive multi-layer zoom.
See the module docs for the layer-threshold model.
Attributes
id(:string) (required) - DOM id; must be unique on the page.sources(:list) (required) - Ordered low → high quality layers. Each entry is a map with::url(required) — the source URL (a plain image or a.dzimanifest).:width(optional) — intrinsic pixel width of this source. Used to compute the zoom range where this layer is "good enough". Omit (or leave nil) for.dzisources; DZI covers all zoom levels natively and is treated as the top layer with infinite headroom.
The first entry is the initial render. The list must contain at least one source.
class(:string) - CSS classes for the viewer container. Defaults to"w-full h-96".Global attributes are accepted.