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 Parameter
For simpler use cases where you want native SVG elements to be clickable without styled HTML buttons, you can add click:1 to any cue:
<g id="ui(uid:rot_triangle, action:toggle, click:1)">
<rect x="0" y="0" width="45" height="24" rx="4" style="fill:#d4af37"/>
<text x="22.5" y="16" style="font-size:10px;text-anchor:middle">TRI</text>
</g>
How click:1 works
- The SVG element remains visible and provides the visual appearance
- An invisible HTML overlay is positioned on top to capture clicks
- Clicks trigger the cue just like a button would
- Visual feedback (brightness change) is applied on click
When to use each approach
| Approach | Best For |
|---|---|
button() |
Styled HTML buttons with labels, colors, fonts |
click:1 |
Native SVG visuals that scale/transform with the score |
click:1 advantages
- SVG visuals scale naturally with zoom/transforms
- Full control over appearance via SVG styling
- Simpler syntax for basic triggers
- Works with any SVG element (rect, circle, path, g, etc.)
- Supports initial visibility state with
visible:false
Example: Toggle buttons with click:1
<!-- Pentagon toggle - native SVG clickable -->
<g id="ui(uid:rot_pentagon, action:toggle, click:1)">
<rect x="0" y="0" width="50" height="30" rx="4" fill="#9370db"/>
<text x="25" y="20" text-anchor="middle" fill="#000">PENT</text>
</g>
Example: Initial state with visible:false
Use visible:false to start the target element hidden when the page loads:
<!-- Triangle starts HIDDEN - click the icon to reveal -->
<g id="ui(uid:rot_triangle, action:toggle, visible:false, click:1)">
<path d="M 20,-18 L 38,18 L 2,18 Z" style="fill:#d4af37;fill-opacity:0.3;stroke:#d4af37"/>
<text x="20" y="38">TRI</text>
</g>
The toggle icon remains visible so performers can click it to show/hide the target element.
Summary
- Use
button(trigger:..., style(...))to add styled HTML buttons with labels and colors. - Use
click:1on any cue for native SVG clickable elements. - Both approaches use invisible HTML overlays to ensure clicks work regardless of SVG stacking order.
- The SVG marker defines where the button/clickable appears.
- The
trigger:or cue expression defines what happens when clicked.
Tip: use ← → or ↑ ↓ to navigate the docs