Scalable animated representations of amazing things in the sky, drawn as dots!! No dependencies, one script. Ten kinds of body and forty‑two named ones, from the Milky Way to Halley's comet. Colour them with six CSS variables, or run them monochrome.
Every control writes the tag on the right. Copy it, paste it, done. Colours only appear in the tag once you change one; everything else is the body's own default.
Recognisable objects, each a mode plus the options and palette that make it that thing. Click one to load it into the playground. Any data attribute still overrides the body's own settings, and the six CSS variables still recolour it.
A neutron star as a lighthouse: dense spinning core, two beams on a magnetic axis tilted off the spin, dipole field lines riding along. When a beam sweeps the camera the whole thing flares.
A spiral at a tilt: logarithmic arms, a bright flattened bulge, dust scatter, bright knots,
the pattern turning slowly. data-orb-arms picks the count: 4 is the Milky Way, 2 is a
grand-design like M51. Wide canvases give it more room.
An emission nebula: overlapping gas clouds as soft dots drifting on a slow noise field,
stretched into wisps, lit from inside by a few young stars with faint diffraction spikes. Each cloud
swirls slowly about its own centre while the whole field drifts; data-orb-spin scales it. data-orb-clouds and data-orb-stars set the counts.
Interstellar's Gargantua. Edge-on accretion disk on Keplerian orbits, far side lensed over the top and under the bottom, photon ring, Doppler-bright on the approaching side. Height sets the shadow, width sets how far the disk reaches (up to 6.5 shadow radii on a 2:1 canvas).
Nucleus down-left, two tails streaming up-right away from an off-canvas sun: a broad curved dust tail and a narrow, faster, flickering ion tail. Particles are born at the nucleus and age out. data-orb-spin scales the flow.
A banded globe with three ring bands and the Cassini gap, tilted about 24°, rings on Keplerian speeds. Back-side ring dots hide behind the planet and dim in its shadow. data-orb-tilt for the ring angle, data-orb-spin for rotation. data-orb-surface swaps the bands for moon, earth or mars; data-orb-phase (0 full, 0.5 new, or cycle) lights it from the side.
A star collapses, blows a shell outward, and the shell fades into a filamentary remnant while the core rebuilds. Loops every data-orb-period seconds, default 6.
Two stars round a barycentre on a tilted orbit, a hot primary and a cooler secondary, with a stream of gas pulled off the secondary curling into the primary. Faint orbit trails. data-orb-spin sets the period.
A dotted sun with a corona of streamers; the moon crosses it every data-orb-period seconds, default 10. The corona only shows near totality, with prominences at the limb and a diamond ring either side.
Set any --orb-* custom property on the canvas or an ancestor. Read every
frame, so a theme switch or a hover rule applies live. Each mode has its own defaults; set one
variable and the rest keep the mode's default. Ink ignores them.
canvas.orb {
--orb-cold: #1E56D8; /* far / receding / outer */
--orb-mid: #7FB0FF; /* mid */
--orb-hot: #EAF3FF; /* near / approaching / core */
--orb-glow: #3D7BFF; /* halo + haze */
--orb-ring: #F2F8FF; /* photon ring (blackhole) */
--orb-shadow: #000000; /* the hole (blackhole) */
}
Use it. One script, then any canvas with class orb. Height is the preset,
width lets a mode stretch. Everything else is a data attribute.
<script src="src/ephemeris.js"></script>
<canvas class=orb width=64 height=64 data-orb-mode=pulsar></canvas>
<canvas class=orb width=64 height=64 data-orb-state=swirling></canvas>
<canvas class=orb width=128 height=64 data-orb-mode=blackhole
data-orb-lite=1 data-orb-space=1></canvas>
// added later? wire them up
Ephemeris.register(someRoot);
Or drive it yourself. Every mode is a plain function, (ctx, size, t, dark, opts),
so it drops into an existing orb engine too.
Ephemeris.draw('galaxy', ctx, 64, t, dark, {
arms: 2, lite: true,
palette: { cold:[10,122,90], mid:[95,216,176], hot:[232,255,246],
glow:[32,180,138], ring:[255,255,255], shadow:[0,0,0] }
});
// into an engine with the same signature
Orbs.MODE_DRAWS.pulsar = Ephemeris.MODES.pulsar.draw;
Orbs.STATE_TO_MODE.pinging = 'pulsar';
(size/300)^0.6; counts follow size