Range selection
Drag-select a phrase to loop it. Extend the range with keyboard arrows. Wire a "loop this section" button in a lesson toolbar. Three methods drive the highlight overlay โ the translucent bar you see behind the selected range โ from your own gesture code, and one convenience method turns whatever is highlighted into a real playback loop. Grab the handles in the demo below to reshape the range; release, and playback loops the newly selected span.
The three methodsโ
api.highlightPlaybackRange(startBeat, endBeat)โ paints the highlight overlay between two beats. Pure visual: it does not change what plays.api.applyPlaybackRangeFromHighlight()โ reads the currently highlighted range, setsapi.playbackRangeto loop that span, and moves the tick position to the start.api.clearPlaybackRangeHighlight()โ clears the overlay. Also pure visual; it does not touchplaybackRange.
Split like this so a selection UI stays responsive during the drag (highlightPlaybackRange on every move), commits the loop only when the user releases (applyPlaybackRangeFromHighlight on drag-end), and clears cleanly (clearPlaybackRangeHighlight on escape or click-outside).
The built-in drag-selectโ
With player.enablePlaybackRangeSelection on, alphaTab drives the same overlay from mouse drags. A drag becomes a range once it reaches a second beat; a press and release on one beat stays a click. By default that click clears the range. Set player.resetPlaybackRangeOnClick to false to keep the range and seek inside it instead. The two-beat threshold and resetPlaybackRangeOnClick are available since 1.9.0. Enabling and disabling interaction covers the details.
The editor patternโ
Wire your drag gesture to the three methods. During the drag, keep painting the range. On release, commit it to a playback loop.
import * as alphaTab from '@coderline/alphatab';
const container = getAlphaTabContainer();
const api = new alphaTab.AlphaTabApi(container, {
core: { file: '/scores/song.gp' },
player: {
playerMode: alphaTab.PlayerMode.EnabledAutomatic,
enableSeekToClick: false,
enablePlaybackRangeSelection: false,
},
});
let dragStart = null;
api.beatMouseDown.on((beat) => {
dragStart = beat;
api.highlightPlaybackRange(beat, beat);
});
api.beatMouseMove.on((beat) => {
if (!dragStart) {
return;
}
api.highlightPlaybackRange(dragStart, beat);
});
api.beatMouseUp.on((beat) => {
if (!dragStart || !beat || beat === dragStart) {
api.clearPlaybackRangeHighlight();
dragStart = null;
return;
}
api.applyPlaybackRangeFromHighlight();
api.isLooping = true;
dragStart = null;
});
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โ
- Selection change events โ the
playbackRangeHighlightChangedevent that streams selection updates while the user drags. - Enabling and disabling interaction โ turn the built-in drag-select off when your own gesture code owns the range.
- Looping a section โ the underlying
playbackRangeandisLoopingtransportapplyPlaybackRangeFromHighlightwrites into. highlightPlaybackRange,applyPlaybackRangeFromHighlight, andclearPlaybackRangeHighlightin the API reference.