Skip to main content

The animation runtime

astra-runtime.js is a dependency-free ES module that animates a figure in the browser. It does not parse astra/1; it reads the figure bundle — the context’s ops, the figure’s parameter values, the scene, the projection and how the figure moves — computes configurations with the same semantics as the Python evaluator, and redraws the figure’s body. The still SVG that the page already contains is the depicted state, so the figure is right before any script runs.

<svg class="astra-figure" …>…<g id="astra-body">…</g></svg>
<div id="astra-transport"></div>
<script type="application/json" id="astra-figure">{ …bundle.json… }</script>
<script type="module">
  import { mount } from './astra-runtime.js';
  const bundle = JSON.parse(document.getElementById('astra-figure').textContent);
  const ctl = mount(document.querySelector('svg.astra-figure'), bundle,
                    { transport: document.getElementById('astra-transport') });
</script>

Controller

call effect
ctl.seek(u) the state a fraction u of a revolution after the depicted one
ctl.play() / ctl.pause() / ctl.toggle() run the kinematic variable at speed seconds per revolution (default 24 s)
ctl.set(name, value) change a parameter value in the drawing (a slider on the eccentricity)
ctl.morph(v) superpositions: 0 the first member, 0.5 both, 1 the second
ctl.step(name) figures of derivations: show what a step speaks of
ctl.state() { u, state, speed, playing, params, morph, members, step }
ctl.onChange(fn) called after every frame with the state

The transport has one row per thing to do: play and the state slider with a readout of the variable (and of the time, when the period has a value); for a superposition a slider that fades between the two members; for a figure of a derivation two buttons that go through the steps, with the step’s proposition, rule and status.

Conventions the runtime honours

  • ?t=<seconds> renders the still at that scene time and never starts the loop; ?static holds the depicted state; prefers-reduced-motion: reduce does the same. ?theme=light|dark sets the theme; ?morph=0..1 and ?step=<name> preset the fade and the step.
  • After every frame the SVG carries data-state and data-ink, an estimate of the inked share of the canvas; a construction that fails in some state sets data-render-error on <html>, as do script errors. These are the conventions of famulus-viz render_check: it photographs an animation at 0.6, 3 and 7 scene seconds and requires the frames to differ and to ink at least 0.2 % of the canvas.
  • The loop is elapsed-time based (a hidden tab pauses it), so playback speed is independent of frame rate.

Two evaluators, one truth

The Python evaluator renders stills and checks propositions; the JS runtime animates. Both implement spec/ops.yaml. spec/ops-vectors.json holds hand-written cases per op, spec/model-vectors.json every context under sampled and attested values in several states, given by the variable and by a time; node tests/js/run_vectors.mjs replays both against the runtime and pytest runs it (a missing node is a failure, not a skip). The placement rules of the figure are stated once (svg/scene.py) and implemented in both renderers line for line.

Embedding

The docs gallery (docs/gallery/*.html) references ../astra-runtime/astra-runtime.js and the tokens CSS; famulus-astra animate (default) inlines runtime, CSS and bundle into one file that can be served from anywhere or opened from disk. Headless renders use the standalone form.

Published by OpenScienceTechnology GmbH · Legal notice · Privacy