button() — Clickable Buttons Inside the Score
The button() helper lets you place HTML buttons aligned to SVG markers in your score.
Each button() marker is an SVG element with an ID that encodes a CueDSL expression; at runtime, Oscilla replaces that marker with a positioned HTML button which can trigger any cue.
Basic Syntax
id="button(
trigger:audio(src:noise, amp:0.9, loop:6, toggle:false, uid:noiseA),
style(size:\"120x45\", color:\"#333\", textcolor:\"#fff\", fontsize:36, active:\"flash\", uid:btnNoise)
)"
General form:
button(
trigger: <cue expression>,
mode:overlay,
tooltip:"Help text",
style(...optional style keys...),
offsetX:<number>,
offsetY:<number>
)
trigger:— required. Any valid CueDSL expression (e.g.nav(...),audio(...),video(...),page(...), etc.).mode:overlay— optional. Keeps the SVG element visible with an invisible click overlay (see below).tooltip:— optional. Adds hover tooltip text.style(...)— optional styling for the HTML button (ignored whenmode:overlay).offsetX,offsetY— optional pixel offsets from the SVG marker position.
The button() expression must appear as the ID of an SVG object:
<rect
id="button(
trigger:audio(src:noise, amp:0.9, loop:6, toggle:false, uid:noiseA),
style(size:\"120x45\", color:\"#333\", textcolor:\"#fff\", fontsize:36, active:\"flash\", uid:btnNoise)
)"
x="100" y="40" width="20" height="20"
/>
Trigger
The trigger: field receives the full cue expression that should run when the button is clicked:
button(
trigger:nav(page:2)
)
button(
trigger:pause(4)
)
button(
trigger:audio(src:noise, amp:0.9, loop:6, toggle:false, uid:noiseA)
)
At runtime, clicking the button calls handleCueTrigger(...) with the parsed trigger AST.
Style Block
The style(...) block controls the appearance and behaviour of the HTML button. For example:
button(
trigger:audio(src:noise, amp:0.9, loop:6, toggle:false, uid:noiseA),
style(
label:\"Noise A\",
size:\"120x45\",
color:\"#333\",
textcolor:\"#fff\",
font:\"Inter\",
fontsize:36,
active:\"flash\",
uid:btnNoise
)
)
Supported style keys
| Key | Type | Description |
|---|---|---|
label |
string | Button text override |
size |
"WxH" |
Width × height in pixels, e.g. "120x45" |
color |
string | Background color (CSS color) |
textcolor |
string | Text color |
font |
string | Font-family name |
fontsize |
number | Font size in px |
active |
string | "flash" to briefly highlight on click |
uid |
string | Identifier for debugging / CSS hooks |
Notes:
- If
style(label:...)is present, it overrides any auto-generated label. - If
style(active:\"flash\")is set, the button gets theoscilla-button-flashableclass and flashes briefly on click.
Overlay Mode (mode:overlay)
By default, button() creates an HTML <button> element and hides the SVG marker. With mode:overlay, the SVG element stays visible and an invisible click overlay captures interactions.
button(
trigger:video(file:intro.mp4, w:960, h:540, closeBtn:1, backdrop:1),
mode:overlay,
tooltip:"Watch tutorial"
)
When to use mode:overlay
- Custom SVG artwork should remain visible (icons, shapes, styled graphics)
- SVG scales/transforms should be preserved
- You want the visual to be part of the score, not an HTML overlay
Example: Tutorial button with custom SVG
<g id="button(trigger:video(file:tutorial.mp4,w:960,h:540,location:fixed,closeBtn:1,backdrop:1),mode:overlay,tooltip:Tutorial)">
<rect x="0" y="0" width="50" height="48" rx="4" style="fill:#4a90d9;stroke:#3070b0"/>
<text x="25" y="35" style="font-size:28px;text-anchor:middle;fill:#fff">?</text>
</g>
The SVG "?" button remains visible; clicking it opens the modal video.
Automatic Label Fallback
If no style(label:...) is provided, Oscilla derives a label from the trigger:
Priority (roughly):
style(label:\"…\")overridetrigger.uid(if present)trigger.action(e.g."nav","audio","page")trigger.page(for page cues)"button"as a final fallback
This means even minimal buttons like:
button(trigger:nav(page:3))
will still get a readable label.
Positioning
Each button() marker is an SVG element that defines where the HTML button should appear.
Runtime behaviour:
-
The engine looks for a suitable container element in the DOM:
#singlePage-content#pageOverlay#scoreInner
-
It computes the SVG marker's bounding box and transform, converts that to screen coordinates, then to container-local coordinates.
-
It creates a
<button>element withposition:absoluteand sets itsleftandtopto match the marker position. -
If the marker is not part of a
reuse(...)clone, the SVG marker is hidden (viavisibility:hidden) so only the HTML button is visible.
Offsets
You can nudge the button relative to the marker with offsetX and offsetY in pixels:
button(
trigger:nav(page:4),
style(label:\"Next Page\"),
offsetX:10,
offsetY:-8
)
Containers and Page Mode
Buttons are designed primarily for page mode overlays:
- In page mode,
button()elements will be placed insidesinglePage-contentorpageOverlay. - If the chosen
containerElaccidentally resolves to an SVG element, Oscilla falls back to#singlePage-content.
This ensures that buttons remain correctly aligned even when the score scrolls or resizes.
Click Behaviour
On click, a button:
- Prevents default and stops event propagation.
- Optionally flashes (
active:\"flash\"). - Invokes
handleCueTrigger(triggerAst, false, true, markerElement)with the trigger AST.
This means button() is essentially a visual trigger surface for any existing cue type.
Managing Buttons Programmatically
Destroy all generated buttons
destroyAllCueButtons();
- Removes all
.oscilla-cue-buttonelements from the DOM. - Calls an internal
_destroyCueButtonif present (for cleanup). - Useful when unloading or reloading a score.
Hide all button() markers in the SVG
hideAllButtonPlaceholders(svgRoot);
- Finds all markers with
id^="button("and sets:opacity: 0pointer-events: none
- This hides the original SVG placeholders (including clones) while leaving the HTML buttons visible.
Alternative: click:1 on osc() elements
The most common interactive button pattern in Oscilla uses osc() directly
with click:1. This keeps the SVG element visible and clickable without
creating a separate HTML button, making it ideal for performance control
surfaces embedded in the score.
<rect id="osc(addr:"gong/a/bypass", click:1, toggle:1, group:gongFaders)"
x="100" y="928" width="90" height="55" rx="6"
style="fill:#666666;stroke:#444444"/>
<text x="145" y="959" text-anchor="middle" fill="white">BYPASS</text>
osc() with click:1 supports the following additional parameters:
| Parameter | Description |
|---|---|
toggle:1 |
Binary toggle; sends explicit 0 or 1 — SC must SET state, not toggle |
radio:name |
Exclusive radio group (only one active at a time) |
labels:'A,B' |
Two-state text: first = off label, second = on label |
group:name |
Register with o2p preset group for state capture/restore |
See cue_osc — Interactive Button Mode for full documentation including SuperCollider examples, sync behaviour, and the correct initial-state pattern.
When to use each approach
| Approach | Best for |
|---|---|
button() |
Styled HTML buttons with custom labels, colors, fonts |
osc(click:1) |
OSC-sending buttons with toggle/radio/label states, embedded in SVG score |
ui(click:1) |
Visibility toggles (show/hide other SVG elements) |
Summary
- Use
button(trigger:..., style(...))for styled HTML buttons with labels and colors. - Use
osc(addr:..., click:1, toggle:1)for OSC-sending buttons with two-state toggle and label support. - Both use invisible HTML overlays so clicks work regardless of SVG stacking order.
- The SVG element defines where the button appears; the cue expression defines what happens.
Tip: use ← → or ↑ ↓ to navigate the docs