Tessera.Viewer (tessera v0.1.0)

Copy Markdown View Source

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

viewer(assigns)

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 .dzi manifest).
    • :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 .dzi sources; 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.