Skip to content

Commit

Permalink
perf: only update on change
Browse files Browse the repository at this point in the history
  • Loading branch information
brandonocasey committed Aug 2, 2019
1 parent 4b325ea commit 57cf88b
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 196 deletions.
45 changes: 27 additions & 18 deletions src/js/control-bar/progress-control/progress-control.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,25 +56,34 @@ class ProgressControl extends Component {
handleMouseMove(event) {
const seekBar = this.getChild('seekBar');

if (seekBar) {
const mouseTimeDisplay = seekBar.getChild('mouseTimeDisplay');
const seekBarEl = seekBar.el();
const seekBarRect = Dom.getBoundingClientRect(seekBarEl);
let seekBarPoint = Dom.getPointerPosition(seekBarEl, event).x;

// The default skin has a gap on either side of the `SeekBar`. This means
// that it's possible to trigger this behavior outside the boundaries of
// the `SeekBar`. This ensures we stay within it at all times.
if (seekBarPoint > 1) {
seekBarPoint = 1;
} else if (seekBarPoint < 0) {
seekBarPoint = 0;
}

if (mouseTimeDisplay) {
mouseTimeDisplay.update(seekBarRect, seekBarPoint);
}
if (!seekBar) {
return;
}

const playProgressBar = seekBar.getChild('playProgressBar');
const mouseTimeDisplay = seekBar.getChild('mouseTimeDisplay');

if (!playProgressBar && !mouseTimeDisplay) {
return;
}

const seekBarEl = seekBar.el();
const seekBarRect = Dom.getBoundingClientRect(seekBarEl);
let seekBarPoint = Dom.getPointerPosition(seekBarEl, event).x;

// The default skin has a gap on either side of the `SeekBar`. This means
// that it's possible to trigger this behavior outside the boundaries of
// the `SeekBar`. This ensures we stay within it at all times.
seekBarPoint = Math.max(0, Math.min(1, seekBarPoint));

if (mouseTimeDisplay) {
mouseTimeDisplay.update(seekBarRect, seekBarPoint);
}

if (playProgressBar) {
playProgressBar.update(seekBarRect, seekBar.percent_);
}

}

/**
Expand Down
95 changes: 43 additions & 52 deletions src/js/control-bar/progress-control/seek-bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,7 @@ class SeekBar extends Slider {
setEventHandlers_() {
this.update = Fn.throttle(Fn.bind(this, this.update), UPDATE_REFRESH_INTERVAL);

this.on(this.player_, 'timeupdate', this.update);
this.on(this.player_, 'ended', this.handleEnded);
this.on(this.player_, 'durationchange', this.update);
this.on(this.player_, ['ended', 'durationchange', 'timeupdate'], this.update);
if (this.player_.liveTracker) {
this.on(this.player_.liveTracker, 'liveedgechange', this.update);
}
Expand All @@ -83,24 +81,29 @@ class SeekBar extends Slider {
this.enableInterval_();

// we just switched back to the page and someone may be looking, so, update ASAP
this.requestAnimationFrame(this.update);
this.update();
}
}

enableInterval_() {
this.clearInterval(this.updateInterval);
if (this.updateInterval) {
return;

this.updateInterval = this.setInterval(() =>{
this.requestAnimationFrame(this.update);
}, UPDATE_REFRESH_INTERVAL);
}
this.updateInterval = this.setInterval(this.update, UPDATE_REFRESH_INTERVAL);
}

disableInterval_(e) {
if (this.player_.liveTracker && this.player_.liveTracker.isLive() && e.type !== 'ended') {
return;
}

if (!this.updateInterval) {
return;
}

this.clearInterval(this.updateInterval);
this.updateInterval = null;
}

/**
Expand Down Expand Up @@ -130,31 +133,36 @@ class SeekBar extends Slider {
* @private
*/
update_(currentTime, percent) {
const liveTracker = this.player_.liveTracker;
let duration = this.player_.duration();
this.requestAnimationFrame(() => {
const liveTracker = this.player_.liveTracker;
let duration = this.player_.duration();

if (liveTracker && liveTracker.isLive()) {
duration = this.player_.liveTracker.liveCurrentTime();
}
if (liveTracker && liveTracker.isLive()) {
duration = this.player_.liveTracker.liveCurrentTime();
}

// machine readable value of progress bar (percentage complete)
this.el_.setAttribute('aria-valuenow', (percent * 100).toFixed(2));

// human readable value of progress bar (time complete)
this.el_.setAttribute(
'aria-valuetext',
this.localize(
'progress bar timing: currentTime={1} duration={2}',
[formatTime(currentTime, duration),
formatTime(duration, duration)],
'{1} of {2}'
)
);

// Update the `PlayProgressBar`.
if (this.bar) {
this.bar.update(Dom.getBoundingClientRect(this.el_), percent);
}
if (this.percent_ !== percent) {
// machine readable value of progress bar (percentage complete)
this.el_.setAttribute('aria-valuenow', (percent * 100).toFixed(2));
this.percent_ = percent;
}

if (this.currentTime_ !== currentTime || this.duration_ !== duration) {
// human readable value of progress bar (time complete)
this.el_.setAttribute(
'aria-valuetext',
this.localize(
'progress bar timing: currentTime={1} duration={2}',
[formatTime(currentTime, duration),
formatTime(duration, duration)],
'{1} of {2}'
)
);

this.currentTime_ = currentTime;
this.duration_ = duration;
}
});
}

/**
Expand All @@ -169,15 +177,11 @@ class SeekBar extends Slider {
* The current percent at a number from 0-1
*/
update(event) {
// if the offsetParent is null, then this element is hidden, in which case
// we don't need to update it.
if (this.el().offsetParent === null) {
return;
}

const percent = super.update();
const currentTime = this.player_.ended() ?
this.player.duration() : this.getCurrentTime_();

this.update_(this.getCurrentTime_(), percent);
this.update_(currentTime, percent);
return percent;
}

Expand All @@ -196,19 +200,6 @@ class SeekBar extends Slider {
this.player_.currentTime();
}

/**
* We want the seek bar to be full on ended
* no matter what the actual internal values are. so we force it.
*
* @param {EventTarget~Event} [event]
* The `timeupdate` or `ended` event that caused this to run.
*
* @listens Player#ended
*/
handleEnded(event) {
this.update_(this.player_.duration(), 1);
}

/**
* Get the percentage of media played so far.
*
Expand All @@ -231,7 +222,7 @@ class SeekBar extends Slider {
percent = currentTime / this.player_.duration();
}

return percent >= 1 ? 1 : (percent || 0);
return percent;
}

/**
Expand Down
4 changes: 4 additions & 0 deletions src/js/control-bar/progress-control/time-tooltip.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Component from '../../component';
import * as Dom from '../../utils/dom.js';
import formatTime from '../../utils/format-time.js';
import * as Fn from '../../utils/fn.js';
import * as browser from '../../utils/browser.js';

/**
* Time tooltips display a time above the progress bar.
Expand All @@ -24,6 +25,9 @@ class TimeTooltip extends Component {
*/
constructor(player, options) {
super(player, options);
if (browser.IS_IOS || browser.IS_ANDROID) {
this.hide();
}
this.update = Fn.throttle(Fn.bind(this, this.update), Fn.UPDATE_REFRESH_INTERVAL);
}

Expand Down
40 changes: 7 additions & 33 deletions src/js/control-bar/time-controls/current-time-display.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,6 @@ import Component from '../../component.js';
*/
class CurrentTimeDisplay extends TimeDisplay {

/**
* Creates an instance of this class.
*
* @param {Player} player
* The `Player` that this class should be attached to.
*
* @param {Object} [options]
* The key/value store of player options.
*/
constructor(player, options) {
super(player, options);
this.on(player, 'ended', this.handleEnded);
}

/**
* Builds the default DOM `className`.
*
Expand All @@ -45,28 +31,16 @@ class CurrentTimeDisplay extends TimeDisplay {
*/
updateContent(event) {
// Allows for smooth scrubbing, when player can't keep up.
const time = (this.player_.scrubbing()) ? this.player_.getCache().currentTime : this.player_.currentTime();

this.updateFormattedTime_(time);
}
let time;

/**
* When the player fires ended there should be no time left. Sadly
* this is not always the case, lets make it seem like that is the case
* for users.
*
* @param {EventTarget~Event} [event]
* The `ended` event that caused this to run.
*
* @listens Player#ended
*/
handleEnded(event) {
if (!this.player_.duration()) {
return;
if (this.player_.ended()) {
time = this.player_.duration();
} else {
time = (this.player_.scrubbing()) ? this.player_.getCache().currentTime : this.player_.currentTime();
}
this.updateFormattedTime_(this.player_.duration());
}

this.updateTextNode_(time);
}
}

/**
Expand Down
7 changes: 2 additions & 5 deletions src/js/control-bar/time-controls/duration-display.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class DurationDisplay extends TimeDisplay {
// Also listen for timeupdate (in the parent) and loadedmetadata because removing those
// listeners could have broken dependent applications/libraries. These
// can likely be removed for 7.0.
this.on(player, 'loadedmetadata', this.throttledUpdateContent);
this.on(player, 'loadedmetadata', this.updateContent);
}

/**
Expand All @@ -63,10 +63,7 @@ class DurationDisplay extends TimeDisplay {
updateContent(event) {
const duration = this.player_.duration();

if (this.duration_ !== duration) {
this.duration_ = duration;
this.updateFormattedTime_(duration);
}
this.updateTextNode_(duration);
}
}

Expand Down
30 changes: 9 additions & 21 deletions src/js/control-bar/time-controls/remaining-time-display.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ class RemainingTimeDisplay extends TimeDisplay {
*/
constructor(player, options) {
super(player, options);
this.on(player, 'durationchange', this.throttledUpdateContent);
this.on(player, 'ended', this.handleEnded);
this.on(player, 'durationchange', this.updateContent);
}

/**
Expand Down Expand Up @@ -64,30 +63,19 @@ class RemainingTimeDisplay extends TimeDisplay {
return;
}

let time;

// @deprecated We should only use remainingTimeDisplay
// as of video.js 7
if (this.player_.remainingTimeDisplay) {
this.updateFormattedTime_(this.player_.remainingTimeDisplay());
if (this.player_.ended()) {
time = 0;
} else if (this.player_.remainingTimeDisplay) {
time = this.player_.remainingTimeDisplay();
} else {
this.updateFormattedTime_(this.player_.remainingTime());
time = this.player_.remainingTime();
}
}

/**
* When the player fires ended there should be no time left. Sadly
* this is not always the case, lets make it seem like that is the case
* for users.
*
* @param {EventTarget~Event} [event]
* The `ended` event that caused this to run.
*
* @listens Player#ended
*/
handleEnded(event) {
if (!this.player_.duration()) {
return;
}
this.updateFormattedTime_(0);
this.updateTextNode_(time);
}
}

Expand Down
Loading

0 comments on commit 57cf88b

Please sign in to comment.