Skip to main content

Selection change events

Sync a right-side properties inspector to the selected range. Move drag handles that ride the edges of the highlight. Show a "5 bars selected" pill above the range while the user drags. Every time the highlight overlay changes โ€” from a user drag, from a programmatic highlightPlaybackRange call, from a clear โ€” alphaTab fires playbackRangeHighlightChanged with the current start and end beats plus the pixel rectangles being painted. The demo below wires drag handles to this event; the event log on the side shows the payload each fire delivers.

startBeat: โ€”
endBeat: โ€”
highlightBlocks: 0

The event payloadโ€‹

The handler receives a PlaybackHighlightChangeEventArgs object. Every field is optional โ€” an empty object arrives when the selection was cleared or the render has not settled yet.

  • startBeat โ€” the Beat where the selection starts. undefined when there is no selection.
  • startBeatBounds โ€” the BeatBounds for that beat, ready to position a marker.
  • endBeat โ€” the Beat where the selection ends.
  • endBeatBounds โ€” the BeatBounds for the end beat.
  • highlightBlocks โ€” the array of Bounds rectangles that make up the overlay. A single-line selection has one entry; a selection spanning three staff systems has three. Each rectangle has x, y, w, h in render coordinates.

The event fires during the drag, not only on release. Use it to keep drag handles pinned to the current edges without polling.

Show it in codeโ€‹

import * as alphaTab from '@coderline/alphatab';

const container = getAlphaTabContainer();
const startHandle = document.getElementById('selection-start-handle');
const endHandle = document.getElementById('selection-end-handle');

const api = new alphaTab.AlphaTabApi(container, {
core: { file: '/scores/song.gp' },
player: { playerMode: alphaTab.PlayerMode.EnabledAutomatic },
});

api.playbackRangeHighlightChanged.on((e) => {
if (!e.highlightBlocks || e.highlightBlocks.length === 0) {
startHandle.hidden = true;
endHandle.hidden = true;
return;
}

const first = e.highlightBlocks[0];
startHandle.hidden = false;
startHandle.style.left = `${first.x}px`;
startHandle.style.top = `${first.y}px`;
startHandle.style.height = `${first.h}px`;

const last = e.highlightBlocks[e.highlightBlocks.length - 1];
endHandle.hidden = false;
endHandle.style.left = `${last.x + last.w}px`;
endHandle.style.top = `${last.y}px`;
endHandle.style.height = `${last.h}px`;
});

getAlphaTabContainer() is a placeholder for the platform-specific step of obtaining the render target. Every other line runs unchanged on all three runtimes.

Where to look nextโ€‹