From 1414906806913d847d904ebd9433dbea1fa9b4cb Mon Sep 17 00:00:00 2001 From: brandonocasey Date: Mon, 29 Jul 2019 17:59:50 -0400 Subject: [PATCH] perf: timer optimizations --- .../progress-control/play-progress-bar.js | 15 ++++ .../control-bar/progress-control/seek-bar.js | 69 ++++++++++++++----- .../progress-control/time-tooltip.js | 17 ++++- .../control-bar/time-controls/time-display.js | 28 +++++++- 4 files changed, 110 insertions(+), 19 deletions(-) diff --git a/src/js/control-bar/progress-control/play-progress-bar.js b/src/js/control-bar/progress-control/play-progress-bar.js index 53283f09f6..ce147effd9 100644 --- a/src/js/control-bar/progress-control/play-progress-bar.js +++ b/src/js/control-bar/progress-control/play-progress-bar.js @@ -3,6 +3,7 @@ */ import Component from '../../component.js'; import {IS_IOS, IS_ANDROID} from '../../utils/browser.js'; +import * as Fn from '../../utils/fn.js'; import './time-tooltip'; @@ -14,6 +15,20 @@ import './time-tooltip'; */ class PlayProgressBar extends Component { + /** + * Creates an instance of this class. + * + * @param {Player} player + * The {@link 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.update = Fn.throttle(Fn.bind(this, this.update), 25); + } + /** * Create the the DOM element for this class. * diff --git a/src/js/control-bar/progress-control/seek-bar.js b/src/js/control-bar/progress-control/seek-bar.js index ea19ff76a3..dcd84e23cd 100644 --- a/src/js/control-bar/progress-control/seek-bar.js +++ b/src/js/control-bar/progress-control/seek-bar.js @@ -54,20 +54,19 @@ 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); - if (this.player_.liveTracker) { - this.on(this.player_.liveTracker, 'liveedgechange', this.update); - } - // when playing, let's ensure we smoothly update the play progress bar // via an interval this.updateInterval = null; - this.on(this.player_, ['playing'], this.enableInterval_); - - this.on(this.player_, ['ended', 'pause', 'waiting'], this.disableInterval_); + this.player_.ready(() => { + this.on(this.player_, ['useractive'], this.userActive_); + this.on(this.player_, ['userinactive'], this.userInactive_); + if (this.player_.userActive()) { + this.userActive_(); + } else { + this.userInactive_(); + } + }); // we don't need to update the play progress if the document is hidden, // also, this causes the CPU to spike and eventually crash the page on IE11. @@ -76,6 +75,38 @@ class SeekBar extends Slider { } } + userActive_() { + if (this.listenersEnabled_) { + return; + } + this.listenersEnabled_ = true; + this.on(this.player_, ['playing'], this.enableInterval_); + this.on(this.player_, ['ended', 'pause', 'waiting'], this.disableInterval_); + this.on(this.player_, 'timeupdate', this.update); + this.on(this.player_, 'ended', this.handleEnded); + this.on(this.player_, 'durationchange', this.update); + if (this.player_.liveTracker) { + this.on(this.player_.liveTracker, 'liveedgechange', this.update); + } + this.enableInterval_(); + } + + userInactive_() { + if (!this.listenersEnabled_) { + return; + } + this.listenersEnabled_ = false; + this.off(this.player_, ['playing'], this.enableInterval_); + this.off(this.player_, ['ended', 'pause', 'waiting'], this.disableInterval_); + this.off(this.player_, 'timeupdate', this.update); + this.off(this.player_, 'ended', this.handleEnded); + this.off(this.player_, 'durationchange', this.update); + if (this.player_.liveTracker) { + this.off(this.player_.liveTracker, 'liveedgechange', this.update); + } + this.disableInterval_(); + + } toggleVisibility_(e) { if (document.hidden) { this.disableInterval_(e); @@ -88,6 +119,9 @@ class SeekBar extends Slider { } enableInterval_() { + if (this.updateInterval) { + return; + } this.clearInterval(this.updateInterval); this.updateInterval = this.setInterval(() =>{ @@ -96,11 +130,18 @@ class SeekBar extends Slider { } disableInterval_(e) { - if (this.player_.liveTracker && this.player_.liveTracker.isLive() && e.type !== 'ended') { + if (!this.updateInterval) { + return; + } + const isLive = this.player_.liveTracker && this.player_.liveTracker.isLive(); + + // live interval continues to update on events not listed + if (isLive && (e.type !== 'ended' || e.type === 'userinactive')) { return; } this.clearInterval(this.updateInterval); + this.updateInterval = null; } /** @@ -169,12 +210,6 @@ 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(); this.update_(this.getCurrentTime_(), percent); diff --git a/src/js/control-bar/progress-control/time-tooltip.js b/src/js/control-bar/progress-control/time-tooltip.js index ce2c26eb65..1dc1c1d840 100644 --- a/src/js/control-bar/progress-control/time-tooltip.js +++ b/src/js/control-bar/progress-control/time-tooltip.js @@ -4,6 +4,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'; /** * Time tooltips display a time above the progress bar. @@ -12,6 +13,20 @@ import formatTime from '../../utils/format-time.js'; */ class TimeTooltip extends Component { + /** + * Creates an instance of this class. + * + * @param {Player} player + * The {@link 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.update = Fn.throttle(Fn.bind(this, this.update), 25); + } + /** * Create the time tooltip DOM element * @@ -88,7 +103,7 @@ class TimeTooltip extends Component { /** * Write the time to the tooltip DOM element. * - * @param {String} content + * @param {string} content * The formatted time for the tooltip. */ write(content) { diff --git a/src/js/control-bar/time-controls/time-display.js b/src/js/control-bar/time-controls/time-display.js index 52861e20cb..847838169a 100644 --- a/src/js/control-bar/time-controls/time-display.js +++ b/src/js/control-bar/time-controls/time-display.js @@ -26,7 +26,33 @@ class TimeDisplay extends Component { constructor(player, options) { super(player, options); this.throttledUpdateContent = throttle(bind(this, this.updateContent), 25); - this.on(player, 'timeupdate', this.throttledUpdateContent); + this.enableUpdateContent_ = bind(this, this.enableUpdateContent_); + this.disableUpdateContent_ = bind(this, this.disableUpdateContent_); + this.player.ready(() => { + this.on(player, 'useractive', this.enableUpdateContent_); + this.on(player, 'userinactive', this.disableUpdateContent_); + if (this.player.userActive()) { + this.enableUpdateContent_(); + } else { + this.disableUpdateContent_(); + } + }); + } + + enableUpdateContent_() { + if (this.updateContentEnabled_) { + return; + } + this.updateContentEnabled_ = true; + this.on(this.player_, 'timeupdate', this.throttledUpdateContent); + } + + disableUpdateContent_() { + if (!this.updateContentEnabled_) { + return; + } + this.updateContentEnabled_ = false; + this.off(this.player_, 'timeupdate', this.throttledUpdateContent); } /**