Skip to content

Commit 608a585

Browse files
authored
feat: Seek bar smooth seeking (#8287)
* refactor(player): decrease the indentation level in the currentTime method * fix(player): cache_.currentTime is not updated when the current time is set Updating cache_.currentTime as soon as the currentTime is set avoids having to wait for the timeupdate event, which results in: - making cache_.currentTime more reliable - updating the progress bar on mouse up after dragging when the media is paused. See also: #6232, #6234, #6370, #6372 * feat: add an option to handle smooth seeking Adds a player option called enableSmoothSeeking, which is false by default, to provide a smoother seeking experience on mobile and desktop devices. Usage: ```javascript // Enables the smooth seeking const player = videojs('player', {enableSmoothSeeking: true}); // Disable the smooth seeking player.options({enableSmoothSeeking: false}); ``` - **player.js** add an `option` called `enableSmoothSeeking` - **time-display.js** add a listener to the `seeking` event if `enableSmoothSeeking` is `true` allowing to update the `CurrentTimeDisplay` and `RemainingTimeDisplay` in real time - **seek-bar.js** `update` the seek bar on `mousemove` event if `enableSmoothSeeking` is `true` - add test cases
1 parent af0fca3 commit 608a585

File tree

4 files changed

+85
-2
lines changed

4 files changed

+85
-2
lines changed

src/js/control-bar/progress-control/seek-bar.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,10 @@ class SeekBar extends Slider {
324324

325325
// Set new time (tell player to seek to new time)
326326
this.userSeek_(newTime);
327+
328+
if (this.player_.options_.enableSmoothSeeking) {
329+
this.update();
330+
}
327331
}
328332

329333
enable() {

src/js/control-bar/time-controls/time-display.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class TimeDisplay extends Component {
2626
constructor(player, options) {
2727
super(player, options);
2828

29-
this.on(player, ['timeupdate', 'ended'], (e) => this.updateContent(e));
29+
this.on(player, ['timeupdate', 'ended', 'seeking'], (e) => this.update(e));
3030
this.updateTextNode_();
3131
}
3232

@@ -71,6 +71,20 @@ class TimeDisplay extends Component {
7171
super.dispose();
7272
}
7373

74+
/**
75+
* Updates the displayed time according to the `updateContent` function which is defined in the child class.
76+
*
77+
* @param {Event} [event]
78+
* The `timeupdate`, `ended` or `seeking` (if enableSmoothSeeking is true) event that caused this function to be called.
79+
*/
80+
update(event) {
81+
if (!this.player_.options_.enableSmoothSeeking && event.type === 'seeking') {
82+
return;
83+
}
84+
85+
this.updateContent(event);
86+
}
87+
7488
/**
7589
* Updates the time display text node with a new time
7690
*

src/js/player.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5413,7 +5413,9 @@ Player.prototype.options_ = {
54135413
breakpoints: {},
54145414
responsive: false,
54155415
audioOnlyMode: false,
5416-
audioPosterMode: false
5416+
audioPosterMode: false,
5417+
// Default smooth seeking to false
5418+
enableSmoothSeeking: false
54175419
};
54185420

54195421
TECH_EVENTS_RETRIGGER.forEach(function(event) {

test/unit/player.test.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3423,3 +3423,66 @@ QUnit.test('should not reset the error when the tech triggers an error that is n
34233423
errorStub.restore();
34243424
log.error.restore();
34253425
});
3426+
3427+
QUnit.test('smooth seeking set to false should not update the display time components or the seek bar', function(assert) {
3428+
const player = TestHelpers.makePlayer({});
3429+
const {
3430+
currentTimeDisplay,
3431+
remainingTimeDisplay,
3432+
progressControl: {
3433+
seekBar
3434+
}
3435+
} = player.controlBar;
3436+
const currentTimeDisplayUpdateContent = sinon.spy(currentTimeDisplay, 'updateContent');
3437+
const remainingTimeDisplayUpdateContent = sinon.spy(remainingTimeDisplay, 'updateContent');
3438+
const seekBarUpdate = sinon.spy(seekBar, 'update');
3439+
3440+
assert.false(player.options().enableSmoothSeeking, 'enableSmoothSeeking is false by default');
3441+
3442+
player.trigger('seeking');
3443+
3444+
assert.ok(currentTimeDisplayUpdateContent.notCalled, 'currentTimeDisplay updateContent was not called');
3445+
assert.ok(remainingTimeDisplayUpdateContent.notCalled, 'remainingTimeDisplay updateContent was not called');
3446+
3447+
seekBar.trigger('mousedown');
3448+
seekBar.trigger('mousemove');
3449+
3450+
assert.ok(seekBarUpdate.notCalled, 'seekBar update was not called');
3451+
3452+
currentTimeDisplayUpdateContent.restore();
3453+
remainingTimeDisplayUpdateContent.restore();
3454+
seekBarUpdate.restore();
3455+
player.dispose();
3456+
});
3457+
3458+
QUnit.test('smooth seeking set to true should update the display time components and the seek bar', function(assert) {
3459+
const player = TestHelpers.makePlayer({enableSmoothSeeking: true});
3460+
const {
3461+
currentTimeDisplay,
3462+
remainingTimeDisplay,
3463+
progressControl: {
3464+
seekBar
3465+
}
3466+
} = player.controlBar;
3467+
const currentTimeDisplayUpdateContent = sinon.spy(currentTimeDisplay, 'updateContent');
3468+
const remainingTimeDisplayUpdateContent = sinon.spy(remainingTimeDisplay, 'updateContent');
3469+
const seekBarUpdate = sinon.spy(seekBar, 'update');
3470+
3471+
assert.true(player.options().enableSmoothSeeking, 'enableSmoothSeeking is true');
3472+
3473+
player.duration(1);
3474+
player.trigger('seeking');
3475+
3476+
assert.ok(currentTimeDisplayUpdateContent.called, 'currentTimeDisplay updateContent was called');
3477+
assert.ok(remainingTimeDisplayUpdateContent.called, 'remainingTimeDisplay updateContent was called');
3478+
3479+
seekBar.trigger('mousedown');
3480+
seekBar.trigger('mousemove');
3481+
3482+
assert.ok(seekBarUpdate.called, 'seekBar update was called');
3483+
3484+
currentTimeDisplayUpdateContent.restore();
3485+
remainingTimeDisplayUpdateContent.restore();
3486+
seekBarUpdate.restore();
3487+
player.dispose();
3488+
});

0 commit comments

Comments
 (0)