Hit Layer Interactivity
The glyphcss hit layer is sparse — you opt-in to interactivity by registering hotspots at specific 3D anchors. No polygon-per-DOM-node overhead.
Why sparse
Section titled “Why sparse”A polycss-style “one DOM node per polygon” model gives you per-polygon events but
balloons the DOM for large meshes (a 10k-triangle GLB → 10k <div>s). glyphcss takes
the opposite trade: a single <pre> for visuals, and only the hotspots you
explicitly register become DOM nodes.
For most real apps this is what you want. You don’t need click handlers on every roof shingle; you need them on the front door.
Authoring hotspots
Section titled “Authoring hotspots”import { GlyphCamera, GlyphScene, GlyphMesh, GlyphHotspot } from "@glyphcss/react";import { octahedronPolygons } from "@glyphcss/core";
const shape = octahedronPolygons({ center: [0, 0, 0], size: 1, color: "#ffcc44" });
<GlyphCamera rotX={25}> <GlyphScene mode="solid" cols={80} rows={24}> <GlyphMesh polygons={shape}> <GlyphHotspot id="top" at={[0, 1, 0]} onClick={() => alert("top vertex")}> <span className="badge">Top</span> </GlyphHotspot> <GlyphHotspot id="bottom" at={[0, -1, 0]} onClick={() => alert("bottom vertex")}> <span className="badge">Bottom</span> </GlyphHotspot> </GlyphMesh> </GlyphScene></GlyphCamera>Each <GlyphHotspot> becomes:
<div class="glyph-hotspot" data-hotspot-id="top" style="position: absolute; left: …; top: …; width: 1ch; height: 2ch"> <span class="badge">Top</span></div>The height is size[1] × cellAspect ch — 2ch at the default aspect — so the box
covers a whole character cell. left/top are reassigned inline each render from the same camera projection
that produced the character grid, anchored at the cell centre — the
.glyph-hotspot rule applies transform: translate(-50%, -50%). There is no
role; add your own semantics if the hotspot is interactive.
Anchors
Section titled “Anchors”at is a world-space Vec3. String anchors like "vertex:42" are not
implemented — compute the coordinate from your polygon data and pass it.
Visibility
Section titled “Visibility”A hotspot whose projected cell is not visible is hidden with display: "none",
staged and applied in the same single write as the rest of the frame — not faded
via opacity. Animate the element yourself if you want a transition.