The lightweight one: a canvas plus play/pause/loop/seek. Use it where a page only needs to replay an already-drawn shape and wants no sky behind it.
<rr0-ufo src="sighting.json"></rr0-ufo>
| Member | Kind | What it does |
|---|---|---|
src | attribute | URL of a recording, fetched on connect and whenever it changes |
sightingData | property | The recording as a plain object — read it back after editing, or set it instead of using src |
sighting | property (read) | The live model: real-world time and place plus the recording's timeline |
loadFromSrc(url) | method (async) | What the attribute triggers internally. Await it when you need the recording to be IN before doing anything else — playing before it resolves finds a zero-length timeline |
play() / pause() | method | Say which state you want, rather than flipping the current one |
togglePlayPause() | method | What the button, the click and the space bar do |
playbackState | property (read) | "stopped", "playing" or "paused" |
currentTime | property | The playhead, in the timeline's own units — not real milliseconds, see positionLabel |
seekableDuration | property (read) | The range currentTime can take |
autoReplayEnabled | property | Looping, on by default. Turn it off if you want the ended event |
positionLabel / durationLabel | property (read) | The position and length already formatted by the element — real clock time when the observation states one |
refresh() | method | Re-reads the duration and repaints — call it after mutating sighting.timeline from outside |
canvasElement / renderer | property (read) | The <canvas>, and the renderer painting on it |
enableClickToPlay | property | Whether a click toggles playback and a double-click toggles fullscreen (both, or neither). Set false where the canvas is yours for something else |
fullscreenTarget | property | Which element the fullscreen button expands. <rr0-scene> sets it to its own stage, so the sky goes fullscreen and not just the overlay |
What it fires#
| Event | Fires | Where to listen |
|---|---|---|
ended | Once, when playback runs off the end without looping. Not on a pause, and not on a scrub to the end | Anywhere: it bubbles and is composed, so it crosses out of <rr0-scene> and <rr0-sighting> and reaches the element you put on the page. This is how you play several recordings in turn |
timedisplaychange | When the counters switch between clock time and elapsed time | Anywhere, same as above |
timeupdate | Every playback tick and every seek, with detail.time | On this element only. It neither bubbles nor is composed, so a page holding an <rr0-scene> has to reach its ufoElement — it is meant for the elements composing this one |
Putting it in your page#
<script type="module" src="https://ufoathome.org/lib/rr0-ufo.mjs"></script>
<rr0-ufo src="sighting.json"></rr0-ufo>
Or, after npm install @rr0/ufoathome: import "@rr0/ufoathome/ufo".
The bundle is 16 KB gzipped and registers the tag itself — nothing else to call.
The hub says what else that involves, and
sharing an observation has the whole example, to try and to copy.