Title & Annotation¶
The viewer supports a title overlay and a Markdown annotation panel with LaTeX math rendering. Both are fixed-position DOM elements — always readable, independent of camera orientation.
See the example script title_annotation.py
for a runnable demonstration.
Title¶
The title parameter (constructor or set_title()) displays a fixed-position
heading at the top of the viewport:
The TitleStyle controls appearance (font_size, color, background).
Annotation Panel¶
The annotation parameter (constructor or set_annotation()) renders
Markdown text with LaTeX math in a fixed-position, scrollable panel
at the bottom of the viewport. The browser uses the marked library for
Markdown → HTML conversion and KaTeX for math formula rendering.
viz = Visualizer(annotation="""## Step 1
The sphere is defined by: $S = o - \\frac{1}{2} r^2 \\infty$
In conformal GA:
$$S \\cdot X = 0$$
""")
# Live update during animation
viz.set_annotation("## Step 2\n\n$R = e^{-i\\theta/2}$")
# Hide the panel
viz.set_annotation(None)
AnnotationStyle¶
Controls the panel's visual appearance:
| Field | Type | Default | Description |
|---|---|---|---|
width |
str |
"100%" |
CSS width |
max_width |
str |
"800px" |
CSS max-width |
max_height |
str |
"250px" |
CSS max-height (scrollable if exceeded) |
font_size |
float |
13 |
Font size in px |
font_family |
str |
"sans-serif" |
CSS font-family |
color |
str |
"#cccccc" |
Text color |
background |
str |
"rgba(0,0,0,0.75)" |
Panel background |
link_color |
str |
"#88ccff" |
Hyperlink color |
code_background |
str |
"rgba(255,255,255,0.1)" |
Inline code background |
padding |
str |
"10px 16px" |
CSS padding |
border_radius |
str |
"4px" |
CSS border-radius |
Mutate the global default via viz.styles.annotation.
LaTeX Math¶
Inline math uses $...$, display-style math uses $$...$$. KaTeX
auto-detects and renders all delimiters in the annotation text. Supported
features include fractions, exponents, Greek letters, integrals, and matrices.
The same rendering pipeline is used for math in figure export footers and in KaTeX-formatted entity labels.
Live Updates¶
set_annotation() pushes immediately via flush() — no manual flush
needed.
Text Editor¶
open_editor() opens a transient, general-purpose multi-line text editor in
the viewer overlay. It is not tied to annotations: when the editor is
closed, the on_close handler receives the edited text (or None when the
user discards it) and decides what to do:
async def on_edited(self, text, event):
if text is not None:
self.viz.set_annotation(text) # e.g. write it back as the annotation
self.viz.open_editor(
"editor",
label="Edit annotation",
value="$a_e$",
on_close=on_edited,
)
on_close(text, event)— async;textis the edited text on ✓ (keep), orNoneon ✕ (discard).- The editor is one-shot: the handler runs once per
open_editor. - Reusable for editing any text, not just annotations.