The <.splat_viewer /> component.
<.splat_viewer src={~p"/scans/room.sog"} height="500px" />Everything the browser needs travels as data attributes on a single element,
which the SplatViewer hook reads on mount. That is deliberate: it means the
viewer survives a LiveView patch that re-renders the element's attributes
without re-mounting it, and it means the server never has to push a message
to get the viewer started.
Validation happens here
Options are checked in Elixir rather than in the hook. A bad :camera is a
compile-or-render-time error with a message naming what was wrong; the same
mistake caught in JavaScript is a console warning nobody sees, on a page that
renders an empty grey box. Anything that can be rejected before it crosses
into the browser is rejected here.
Summary
Functions
Renders a Gaussian splat.
Functions
@spec splat_viewer(map()) :: Phoenix.LiveView.Rendered.t()
Renders a Gaussian splat.
Attributes
:src is the only required one. Point it at a .sog file — the compressed
format splat_tools produces, roughly 45× smaller than the PLY a trainer
emits. A .ply will load, and on a real capture it will cost your visitor a
hundred megabytes to do it.
Examples
<.splat_viewer src={~p"/scans/room.sog"} />
<.splat_viewer
src={~p"/scans/room.sog"}
camera={@scan.camera}
height="600px"
autorotate
class="rounded-lg shadow"
/>Sizing
:height sets the element's height directly. For a responsive box, leave it
alone and use :class with an aspect-ratio utility — the canvas fills its
container and follows it through a ResizeObserver, so either works.
Attributes
src(:string) (required) - URL of the .sog (or .ply) file to display.id(:string) - DOM id; generated from the src when omitted, which is enough when there is one per page. Defaults tonil.camera(:any) - Starting viewpoint — aSplatViewer.Camera, or a map withposition,targetand optionallyfov. Without one the viewer frames the scene's bounding box, which is a guess;SplatTools.prepare/3derives a better one at conversion time.Defaults to
nil.height(:string) - CSS height for the container. Defaults to"480px".autorotate(:boolean) - slowly orbit until the visitor interacts, then stop and stay stopped. Defaults tofalse.background(:string) - hex colour behind the splat — #rgb, #rgba, #rrggbb or #rrggbbaa. Defaults to"#111318".dpr_cap(:float) - Ceiling on device pixel ratio. The reason mobile struggles with splats is overdraw and alpha blending on a tiled GPU, not arithmetic, so rendering a 3× backing store costs nine times the fill rate for a screen nobody is holding to their eye. Capping is the single most effective mobile lever.Defaults to
2.0.pause_offscreen(:boolean) - stop rendering while the element is scrolled out of view or the tab is hidden. Defaults totrue.interactive(:boolean) - allow orbit, pan and zoom. Defaults totrue.class(:string) - classes for the container element. Defaults tonil.engine_url(:string) - Where to load the rendering engine from, overridingSplatViewer.engine_path/0for this element.Defaults to
nil.Global attributes are accepted.