Skip to content

Commit

Permalink
Merge pull request #658 from bitmovin/feature/improve-seekbar-interac…
Browse files Browse the repository at this point in the history
…tion

Improve Seekbar mouse handling
  • Loading branch information
stonko1994 authored Dec 11, 2024
2 parents 76c794e + 0f1d5ec commit 67735c4
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 29 deletions.
8 changes: 6 additions & 2 deletions src/scss/skin-super-modern/components/_seekbar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,19 @@ $seekbar-height: .3125em;
@include hidden;
@include focusable;

border-radius: 1em;
cursor: pointer;
font-size: 1em;
height: $seekbar-height;
margin: calc((1em - $seekbar-height) / 2) 0;
overflow: hidden;
position: relative;
width: 100%;

.#{$prefix}-seekbar-bars {
@extend %bar;
border-radius: 1em;
overflow: hidden;
}

.#{$prefix}-seekbar-backdrop {
@extend %bar;
background-color: transparentize($color-primary, .8);
Expand Down
44 changes: 20 additions & 24 deletions src/ts/components/seekbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,6 @@ export interface SeekBarConfig extends ComponentConfig {
* Bar will be vertical instead of horizontal if set to true.
*/
vertical?: boolean;
/**
* If set to true the seekBarPlaybackPositionMarker will be rendered
* directly inside the seekbar container. Necessary when using the super-modern-ui skin
* Default: false
*/
renderSeekBarPlaybackPositionMarkerInOuterSeekBar?: boolean;
/**
* The interval in milliseconds in which the playback position on the seek bar will be updated. The shorter the
* interval, the smoother it looks and the more resource intense it is. The update interval will be kept as steady
Expand Down Expand Up @@ -171,7 +165,6 @@ export class SeekBar extends Component<SeekBarConfig> {
snappingRange: 1,
enableSeekPreview: true,
snappingEnabled: true,
renderSeekBarPlaybackPositionMarkerInOuterSeekBar: false,
}, this.config);

this.label = this.config.label;
Expand Down Expand Up @@ -249,10 +242,17 @@ export class SeekBar extends Component<SeekBarConfig> {

uimanager.onControlsShow.subscribe(() => {
this.isUiShown = true;
if (!player.isLive() && !this.smoothPlaybackPositionUpdater.isActive()) {
playbackPositionHandler(null, true);
this.smoothPlaybackPositionUpdater.start();
}
});

uimanager.onControlsHide.subscribe(() => {
this.isUiShown = false;
if (this.smoothPlaybackPositionUpdater.isActive()) {
this.smoothPlaybackPositionUpdater.clear();
}
});

let isPlaying = false;
Expand Down Expand Up @@ -294,7 +294,7 @@ export class SeekBar extends Component<SeekBarConfig> {
// Update playback position only in paused state or in the initial startup state where player is neither
// paused nor playing. Playback updates are handled in the Timeout below.
const isInInitialStartupState = this.config.smoothPlaybackPositionUpdateIntervalMs === SeekBar.SMOOTH_PLAYBACK_POSITION_UPDATE_DISABLED
|| forceUpdate || player.isPaused();
|| forceUpdate || player.isPaused();
const isNeitherPausedNorPlaying = player.isPaused() === player.isPlaying();

if ((isInInitialStartupState || isNeitherPausedNorPlaying) && !this.isSeeking()) {
Expand Down Expand Up @@ -330,12 +330,12 @@ export class SeekBar extends Component<SeekBarConfig> {
scrubbing = false;
};

let onPlayerSeeked = (event: PlayerEventBase = null, forceUpdate: boolean = false ) => {
let onPlayerSeeked = (event: PlayerEventBase = null) => {
isPlayerSeeking = false;
this.setSeeking(false);

// update playback position when a seek has finished
playbackPositionHandler(event, forceUpdate);
playbackPositionHandler(event, true);
};

let restorePlayingState = function () {
Expand Down Expand Up @@ -668,6 +668,10 @@ export class SeekBar extends Component<SeekBarConfig> {
});
this.seekBar = seekBar;

const seekBarBarsContainer = new DOM('div', {
'class': this.prefixCss('seekbar-bars'),
});

// Indicator that shows the buffer fill level
let seekBarBufferLevel = new DOM('div', {
'class': this.prefixCss('seekbar-bufferlevel'),
Expand Down Expand Up @@ -703,12 +707,10 @@ export class SeekBar extends Component<SeekBarConfig> {
});
this.seekBarMarkersContainer = seekBarChapterMarkersContainer;

seekBar.append(this.seekBarBackdrop, this.seekBarBufferPosition, this.seekBarSeekPosition,
seekBarBarsContainer.append(this.seekBarBackdrop, this.seekBarBufferPosition, this.seekBarSeekPosition,
this.seekBarPlaybackPosition, this.seekBarMarkersContainer);

if (!this.config.renderSeekBarPlaybackPositionMarkerInOuterSeekBar) {
seekBar.append(this.seekBarPlaybackPositionMarker);
}
seekBar.append(seekBarBarsContainer, this.seekBarPlaybackPositionMarker);

let seeking = false;

Expand Down Expand Up @@ -747,14 +749,12 @@ export class SeekBar extends Component<SeekBarConfig> {
this.onSeekedEvent(targetPercentage);
};

let domElementToListen: DOM = this.config.renderSeekBarPlaybackPositionMarkerInOuterSeekBar ? seekBarContainer : seekBar;

// A seek always start with a touchstart or mousedown directly on the seekbar.
// To track a mouse seek also outside the seekbar (for touch events this works automatically),
// so the user does not need to take care that the mouse always stays on the seekbar, we attach the mousemove
// and mouseup handlers to the whole document. A seek is triggered when the user lifts the mouse key.
// A seek mouse gesture is thus basically a click with a long time frame between down and up events.
domElementToListen.on('touchstart mousedown', (e: MouseEvent | TouchEvent) => {
seekBar.on('touchstart mousedown', (e: MouseEvent | TouchEvent) => {
let isTouchEvent = BrowserUtils.isTouchSupported && this.isTouchEvent(e);

// Prevent selection of DOM elements (also prevents mousedown if current event is touchstart)
Expand All @@ -776,7 +776,7 @@ export class SeekBar extends Component<SeekBarConfig> {
});

// Display seek target indicator when mouse hovers or finger slides over seekbar
domElementToListen.on('touchmove mousemove', (e: MouseEvent | TouchEvent) => {
seekBar.on('touchmove mousemove', (e: MouseEvent | TouchEvent) => {
e.preventDefault();

if (seeking) {
Expand All @@ -794,7 +794,7 @@ export class SeekBar extends Component<SeekBarConfig> {
});

// Hide seek target indicator when mouse or finger leaves seekbar
domElementToListen.on('touchend mouseleave', (e: MouseEvent | TouchEvent) => {
seekBar.on('touchend mouseleave', (e: MouseEvent | TouchEvent) => {
e.preventDefault();

this.setSeekPosition(0);
Expand All @@ -810,10 +810,6 @@ export class SeekBar extends Component<SeekBarConfig> {
seekBarContainer.append(this.label.getDomElement());
}

if (this.config.renderSeekBarPlaybackPositionMarkerInOuterSeekBar) {
seekBarContainer.append(seekBarPlaybackPositionMarker);
}

return seekBarContainer;
}

Expand Down Expand Up @@ -1107,7 +1103,7 @@ export class SeekBar extends Component<SeekBarConfig> {
this.refreshPlaybackPosition();
}

/**
/**
* Checks if TouchEvent is supported.
* @returns {boolean} true if TouchEvent not undefined, else false
*/
Expand Down
6 changes: 3 additions & 3 deletions src/ts/uifactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ export namespace UIFactory {
timeLabelMode: PlaybackTimeLabelMode.CurrentTime,
hideInLivePlayback: true,
}),
new SeekBar({ label: new SeekBarLabel(), renderSeekBarPlaybackPositionMarkerInOuterSeekBar: true }),
new SeekBar({ label: new SeekBarLabel() }),
new PlaybackTimeLabel({
timeLabelMode: PlaybackTimeLabelMode.TotalTime,
cssClasses: ['text-right'],
Expand Down Expand Up @@ -598,7 +598,7 @@ export namespace UIFactory {
timeLabelMode: PlaybackTimeLabelMode.CurrentTime,
hideInLivePlayback: true,
}),
new SeekBar({ label: new SeekBarLabel(), renderSeekBarPlaybackPositionMarkerInOuterSeekBar: true }),
new SeekBar({ label: new SeekBarLabel() }),
new PlaybackTimeLabel({
timeLabelMode: PlaybackTimeLabelMode.TotalTime,
cssClasses: ['text-right'],
Expand All @@ -610,7 +610,7 @@ export namespace UIFactory {
components: [
new PlaybackToggleButton(),
new VolumeToggleButton(),
new VolumeSlider({ renderSeekBarPlaybackPositionMarkerInOuterSeekBar: true }),
new VolumeSlider(),
new Spacer(),
new PictureInPictureToggleButton(),
new AirPlayToggleButton(),
Expand Down

0 comments on commit 67735c4

Please sign in to comment.