-
Notifications
You must be signed in to change notification settings - Fork 236
Description
Is there an existing issue for this?
- I have searched the existing issues
Current Behavior
When a selection range is active (via click-drag or playbackRange) and the browser/container is resized, the selection highlight rectangles remain at their pre-resize positions. The highlight becomes visually misaligned with the re-rendered score, where the selection is offset horizontally, the wrong width, or on the wrong staff system line.
Expected Behavior
After a resize triggers a re-render, the selection highlight should reposition to match the new layout coordinates.
Steps To Reproduce
- Load a GuitarPro file
- Click-drag to select a range of measures (or set playbackRange)
- Resize the browser window or container so AlphaTab re-renders the score
- Observe: the selection highlight rectangles are at the old positions, not aligned with the re-rendered measures
Link to jsFiddle, CodePen, Project
No response
Version and Environment
alphaTab 1.8.1
Browser: Electron 40 / Chrome 144 (also reproducible in standard browsers)
Windows 11Platform
Web
Anything else?
Root cause is in AlphaTabApiBase. The postRenderFinished handler calls _cursorSelectRange(this._selectionStart, this._selectionEnd) to re-apply the selection after re-render. However, _cursorSelectRange caches beat bounds on the selection objects:
if (!startBeat.bounds) {
startBeat.bounds = cache.findBeat(startBeat.beat) ?? undefined;
}
if (!endBeat.bounds) {
endBeat.bounds = cache.findBeat(endBeat.beat) ?? undefined;
}Since bounds was populated from the pre-resize layout, it's still truthy, so cache.findBeat() is never called, and the stale coordinates (realBounds.x, realBounds.w, visualBounds.y, etc.) are used to position the highlight rectangles.
Suggested fix is to clear the cached bounds before re-applying the selection in postRenderFinished:
this._renderer.postRenderFinished.on(() => {
if (!this._selectionStart || !this._hasCursor || !this.settings.player.enableUserInteraction) {
return;
}
// Force fresh coordinate lookup from the new boundsLookup cache
if (this._selectionStart) {
this._selectionStart.bounds = undefined;
}
if (this._selectionEnd) {
this._selectionEnd.bounds = undefined;
}
this._cursorSelectRange(this._selectionStart, this._selectionEnd);
});Metadata
Metadata
Assignees
Labels
Type
Projects
Status