Starfield Hero
A landing-page hero, not a scene demo — three concentric shells of points at increasing radius and decreasing size and speed, so nearer stars visibly slide past farther ones purely from each shell spinning at its own rate. A slow camera float/pan and a subtle fog give it depth without any per-frame geometry rebuilding. On top, an ordinary Domphy DOM tree (heading, copy, CTA button) is absolutely positioned over the canvas — same element tree, no portal, no iframe.
How it works
- DOM-over-canvas composition: the host is a
position: relativediv containing two absolutely-positioned children — thethree()canvas layer and a DOM overlay layer. Settingstyle.position: "absolute"directly on the canvas-host div wins over thethree()patch's ownposition: relativedefault, since a native element's own style always wins over a patch's — see theThreeOptionscontract. - Layered depth via independent spin rates: each star shell is its own
pointsnode with its ownonFrame, rotating at a differentspinSpeed— no positions are ever rewritten per frame, only each shell's own rotation. SeeonFrame. - Shared dark tone context: the overlay div sets
dataTone: "shift-16"(a dark edge anchor), so every descendant patch —heading(),paragraph(),small(),button()— resolves itsthemeColor()calls against that dark surface automatically, with no color overrides needed on any of them. - DOM event driving a canvas prop: the CTA's
onClickbumps a plainState<number>; the near shell'sonFramereads it untracked each tick (the same pulse-on-change technique Interactive Grid uses for its click bump) to fire a brief forward camera "warp" dash that eases back out. - Explicit vertex colors on the near shell: the closest shell is the only one built with a
bufferAttributecolor channel (attach: "attributes-color") so a scattered minority of points can lean warm or cool against the mostly-white base — seeattachinference for whybufferAttributealways needs an explicitattachpath. - Glowing points, not flat dots: each shell's
pointsMaterialgets amap— a soft radial-gradient sprite drawn once onto aCanvasTexture— combined withblending: AdditiveBlending.sizeAttenuation: falsekeeps each shell's point size fixed in screen pixels (3.6px near, 2px mid, 1px far) instead of shrinking with camera distance, so the far shell fades out via fog rather than just growing small and dim. frameloop: "always": the drift is continuous and time-based, not state-driven, so nothing ever callsinvalidate()— see frameloop modes for why"demand"would freeze this scene on its first frame.