Skip to content

Commit

Permalink
Limit thumbnail preview to UI bounds
Browse files Browse the repository at this point in the history
  • Loading branch information
felix-hoc committed Dec 18, 2024
1 parent 0a55fb1 commit fefcd7f
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 3 deletions.
23 changes: 20 additions & 3 deletions src/ts/components/seekbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,10 @@ export class SeekBar extends Component<SeekBarConfig> {
private seekBarMarkersContainer: DOM;
private timelineMarkersHandler: TimelineMarkersHandler;

private uiBoundingRect: DOMRect;

private player: PlayerAPI;
private uiManager: UIInstanceManager;

protected seekBarType: SeekBarType;

Expand Down Expand Up @@ -220,6 +223,7 @@ export class SeekBar extends Component<SeekBarConfig> {
super.configure(player, uimanager);

this.player = player;
this.uiManager = uimanager;

// Apply scaling transform to the backdrop bar to have all bars rendered similarly
// (the call must be up here to be executed for the volume slider as well)
Expand Down Expand Up @@ -453,6 +457,7 @@ export class SeekBar extends Component<SeekBarConfig> {
// is positioned absolutely and must therefore be updated when the size of the seekbar changes.
player.on(player.exports.PlayerEvent.PlayerResized, () => {
this.refreshPlaybackPosition();
this.uiBoundingRect = this.uiManager.getUI().getDomElement().get(0).getBoundingClientRect();
});
// Additionally, when this code is called, the seekbar is not part of the UI yet and therefore does not have a size,
// resulting in a wrong initial position of the marker. Refreshing it once the UI is configured solved this issue.
Expand Down Expand Up @@ -1020,6 +1025,20 @@ export class SeekBar extends Component<SeekBarConfig> {
this.seekBarEvents.onSeek.dispatch(this);
}

private updateLabelPosition = (seekPositionPercentage: number) => {
const labelDomElement = this.label.getDomElement();
labelDomElement.css({
'left': seekPositionPercentage + '%',
'transform': null,
});

// TODO: Re-test `requestAnimationFrame` to prevent forced synchronous layout calculation
if (!this.uiBoundingRect) {
this.uiBoundingRect = this.uiManager.getUI().getDomElement().get(0).getBoundingClientRect();
}
this.label.ensureWithinBounds(this.uiBoundingRect);
};

protected onSeekPreviewEvent(percentage: number, scrubbing: boolean) {
let snappedMarker = this.timelineMarkersHandler && this.timelineMarkersHandler.getMarkerAtPosition(percentage);

Expand All @@ -1043,9 +1062,7 @@ export class SeekBar extends Component<SeekBarConfig> {
}

if (this.label) {
this.label.getDomElement().css({
'left': seekPositionPercentage + '%',
});
this.updateLabelPosition(seekPositionPercentage);
}

this.seekBarEvents.onSeekPreview.dispatch(this, {
Expand Down
28 changes: 28 additions & 0 deletions src/ts/components/seekbarlabel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,34 @@ export class SeekBarLabel extends Container<SeekBarLabelConfig> {
}
};

public ensureWithinBounds = (bounds: DOMRect) => {
// TODO move into CSS
const overflowMargin = 8;

const labelBounding = this.container.getDomElement().get(0).getBoundingClientRect();

let preventOverflowOffset = 0;
if (labelBounding.right + overflowMargin > bounds.right) {
preventOverflowOffset = labelBounding.right - bounds.right + overflowMargin;
} else if (labelBounding.left - overflowMargin < bounds.left) {
preventOverflowOffset = labelBounding.left - bounds.left - overflowMargin;
}

if (preventOverflowOffset !== 0) {
this.getDomElement().css({
transform: `translateX(${-preventOverflowOffset}px)`,
});

this.caret.getDomElement().css({
transform: `translateX(${preventOverflowOffset}px)`,
});
} else {
this.caret.getDomElement().css({
transform: `translateX(${0}px)`,
});
}
}

/**
* Sets arbitrary text on the label.
* @param text the text to show on the label
Expand Down

0 comments on commit fefcd7f

Please sign in to comment.