From 894dd9eb7477d4910be184cb16a5835638df319e Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Fri, 22 Mar 2019 10:47:26 -0400 Subject: [PATCH] perf(seek-bar): don't update play progress when document is hidden (#5879) The seek bar updates on a 30ms interval to have a nice, smooth transition as time ticks forward. Unfortunately, IE11 has some performance issues with interval when the document is hidden. This doesn't appear to be an issue when using setTimeout but using a setTimeout was causing the play progress to appear very jerky in comparison. Instead, we should just not update the play progress when the document is hidden. Besides solving the issue in IE11, it makes sense to do as no one could be seeing the progress bar. In addition, update() is now a no-op if the seek-bar element isn't visible. Fixes #5575 --- .../control-bar/progress-control/seek-bar.js | 57 ++++++++++++++----- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/src/js/control-bar/progress-control/seek-bar.js b/src/js/control-bar/progress-control/seek-bar.js index a1024ef5d..2c5395b3c 100644 --- a/src/js/control-bar/progress-control/seek-bar.js +++ b/src/js/control-bar/progress-control/seek-bar.js @@ -9,6 +9,7 @@ import * as Fn from '../../utils/fn.js'; import formatTime from '../../utils/format-time.js'; import {silencePromise} from '../../utils/promise'; import keycode from 'keycode'; +import document from 'global/document'; import './load-progress-bar.js'; import './play-progress-bar.js'; @@ -64,24 +65,42 @@ class SeekBar extends Slider { // via an interval this.updateInterval = null; - this.on(this.player_, ['playing'], () => { - this.clearInterval(this.updateInterval); + this.on(this.player_, ['playing'], this.enableInterval_); - this.updateInterval = this.setInterval(() =>{ - this.requestAnimationFrame(() => { - this.update(); - }); - }, UPDATE_REFRESH_INTERVAL); - }); + this.on(this.player_, ['ended', 'pause', 'waiting'], this.disableInterval_); - this.on(this.player_, ['ended', 'pause', 'waiting'], (e) => { - if (this.player_.liveTracker && this.player_.liveTracker.isLive() && e.type !== 'ended') { - return; - } + // 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. + if ('hidden' in document && 'visibilityState' in document) { + this.on(document, 'visibilitychange', this.toggleVisibility_); + } + } - this.clearInterval(this.updateInterval); - }); + toggleVisibility_(e) { + if (document.hidden) { + this.disableInterval_(e); + } else { + this.enableInterval_(); + // we just switched back to the page and someone may be looking, so, update ASAP + this.requestAnimationFrame(this.update); + } + } + + enableInterval_() { + this.clearInterval(this.updateInterval); + + this.updateInterval = this.setInterval(() =>{ + this.requestAnimationFrame(this.update); + }, UPDATE_REFRESH_INTERVAL); + } + + disableInterval_(e) { + if (this.player_.liveTracker && this.player_.liveTracker.isLive() && e.type !== 'ended') { + return; + } + + this.clearInterval(this.updateInterval); } /** @@ -133,7 +152,9 @@ class SeekBar extends Slider { ); // Update the `PlayProgressBar`. - this.bar.update(Dom.getBoundingClientRect(this.el_), percent); + if (this.bar) { + this.bar.update(Dom.getBoundingClientRect(this.el_), percent); + } } /** @@ -148,6 +169,12 @@ 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);