Inspired by the Nancy Grace Roman Space Telescope’s approaching launch: a planet orbits a star, and whenever it crosses in front (from our point of view) it blocks a sliver of the starlight. That’s the transit method Kepler, TESS, and friends use to find exoplanets — no direct image of the planet required, just a very patient brightness meter. This simulates the geometry and plots the resulting light curve in real time.
Three sliders: planet size (bigger planet, deeper dip), orbit offset (how far off-center the orbit passes — push it far enough and the transit misses the star entirely, same as a real system with the wrong inclination), and orbit speed (for watching comfortably, not physically calibrated to any real period).
Reuse
src/transit.js is the whole model, zero dependencies:
circleOverlapArea(d, R, r)— area where two circles overlap, standard circle-circle intersection (“lens”) formula.transitFlux(d, starRadius, planetRadius)— normalized brightness (1 = unblocked) given the planet’s projected distance from star center.orbitPosition(t, { orbitRadius, period, impactParam })andsampleTransit(t, params)— position + flux together for one time sample.maxTransitDepth(starRadius, planetRadius)— the dip you’d see at a dead-center transit, independent of impact parameter.
Feed sampleTransit a time series and you have a light curve; feed it live
t values and you have this demo.
Gotchas
- The orbit is simplified to a flat plane offset by a constant impact parameter rather than a true inclined circle — accurate near transit (the only part worth animating), not for the rest of the orbit.
- No limb darkening: real transits dip faster at ingress/egress and have a flatter bottom. This one’s dip is the pure circle-overlap curve.
- The demo bundles its own copy of
transit.js(self-contained by contract); re-copy after editingsrc/. scripts/screenshot-demo.mjsregeneratesthumb.png— it slows the orbit and pins a small offset so it reliably lands mid-transit before shooting.