Fix play logo (datarhei/restreamer#845, datarhei/restreamer#847)
This commit is contained in:
parent
8958f47462
commit
eac4440d3b
@ -47,7 +47,7 @@
|
||||
"util": "^0.12.5",
|
||||
"uuid": "^10.0.0",
|
||||
"video.js": "^8.17.3",
|
||||
"videojs-overlay": "^3.1.0"
|
||||
"videojs-overlay": "^4.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
@ -95,4 +95,4 @@
|
||||
"react-error-overlay": "^6.0.11"
|
||||
},
|
||||
"resolutions": {}
|
||||
}
|
||||
}
|
||||
758
public/_player/videojs/dist/videojs-overlay.js
vendored
758
public/_player/videojs/dist/videojs-overlay.js
vendored
@ -1,386 +1,420 @@
|
||||
/*! @name videojs-overlay @version 2.1.5 @license Apache-2.0 */
|
||||
'use strict';
|
||||
/*! @name videojs-overlay @version 4.0.0 @license Apache-2.0 */
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('video.js')) :
|
||||
typeof define === 'function' && define.amd ? define(['video.js'], factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.videojsOverlay = factory(global.videojs));
|
||||
})(this, (function (videojs) { 'use strict';
|
||||
|
||||
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
|
||||
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
||||
|
||||
var videojs = _interopDefault(require('video.js'));
|
||||
var window = _interopDefault(require('global/window'));
|
||||
var videojs__default = /*#__PURE__*/_interopDefaultLegacy(videojs);
|
||||
|
||||
function _inheritsLoose(subClass, superClass) {
|
||||
subClass.prototype = Object.create(superClass.prototype);
|
||||
subClass.prototype.constructor = subClass;
|
||||
subClass.__proto__ = superClass;
|
||||
}
|
||||
const initOverlayComponent = videojs => {
|
||||
const Component = videojs.getComponent('Component');
|
||||
const dom = videojs.dom || videojs;
|
||||
|
||||
function _assertThisInitialized(self) {
|
||||
if (self === void 0) {
|
||||
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
||||
}
|
||||
/**
|
||||
* Whether the value is a `Number`.
|
||||
*
|
||||
* Both `Infinity` and `-Infinity` are accepted, but `NaN` is not.
|
||||
*
|
||||
* @param {Number} n
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
return self;
|
||||
}
|
||||
/* eslint-disable no-self-compare */
|
||||
const isNumber = n => typeof n === 'number' && n === n;
|
||||
/* eslint-enable no-self-compare */
|
||||
|
||||
var version = "2.1.5";
|
||||
/**
|
||||
* Whether a value is a string with no whitespace.
|
||||
*
|
||||
* @param {string} s
|
||||
* @return {boolean}
|
||||
*/
|
||||
const hasNoWhitespace = s => typeof s === 'string' && /^\S+$/.test(s);
|
||||
|
||||
var defaults = {
|
||||
align: 'top-left',
|
||||
class: '',
|
||||
content: 'This overlay will show up while the video is playing',
|
||||
debug: false,
|
||||
showBackground: true,
|
||||
attachToControlBar: false,
|
||||
overlays: [{
|
||||
start: 'playing',
|
||||
end: 'paused'
|
||||
}]
|
||||
};
|
||||
var Component = videojs.getComponent('Component');
|
||||
var dom = videojs.dom || videojs;
|
||||
var registerPlugin = videojs.registerPlugin || videojs.plugin;
|
||||
/**
|
||||
* Whether the value is a `Number`.
|
||||
*
|
||||
* Both `Infinity` and `-Infinity` are accepted, but `NaN` is not.
|
||||
*
|
||||
* @param {Number} n
|
||||
* @return {Boolean}
|
||||
*/
|
||||
/**
|
||||
* Overlay component.
|
||||
*
|
||||
* @class Overlay
|
||||
* @extends {videojs.Component}
|
||||
*/
|
||||
class Overlay extends Component {
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
['start', 'end'].forEach(key => {
|
||||
const value = this.options_[key];
|
||||
if (isNumber(value)) {
|
||||
this[key + 'Event_'] = 'timeupdate';
|
||||
} else if (hasNoWhitespace(value)) {
|
||||
this[key + 'Event_'] = value;
|
||||
|
||||
/* eslint-disable no-self-compare */
|
||||
// An overlay MUST have a start option. Otherwise, it's pointless.
|
||||
} else if (key === 'start') {
|
||||
throw new Error('invalid "start" option; expected number or string');
|
||||
}
|
||||
});
|
||||
|
||||
var isNumber = function isNumber(n) {
|
||||
return typeof n === 'number' && n === n;
|
||||
};
|
||||
/* eslint-enable no-self-compare */
|
||||
// video.js does not like components with multiple instances binding
|
||||
// events to the player because it tracks them at the player level,
|
||||
// not at the level of the object doing the binding. This could also be
|
||||
// solved with Function.prototype.bind (but not videojs.bind because of
|
||||
// its GUID magic), but the anonymous function approach avoids any issues
|
||||
// caused by crappy libraries clobbering Function.prototype.bind.
|
||||
// - https://github.com/videojs/video.js/issues/3097
|
||||
['endListener_', 'rewindListener_', 'startListener_'].forEach(name => {
|
||||
this[name] = e => Overlay.prototype[name].call(this, e);
|
||||
});
|
||||
|
||||
/**
|
||||
* Whether a value is a string with no whitespace.
|
||||
*
|
||||
* @param {String} s
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
|
||||
var hasNoWhitespace = function hasNoWhitespace(s) {
|
||||
return typeof s === 'string' && /^\S+$/.test(s);
|
||||
};
|
||||
/**
|
||||
* Overlay component.
|
||||
*
|
||||
* @class Overlay
|
||||
* @extends {videojs.Component}
|
||||
*/
|
||||
|
||||
|
||||
var Overlay =
|
||||
/*#__PURE__*/
|
||||
function (_Component) {
|
||||
_inheritsLoose(Overlay, _Component);
|
||||
|
||||
function Overlay(player, options) {
|
||||
var _this;
|
||||
|
||||
_this = _Component.call(this, player, options) || this;
|
||||
['start', 'end'].forEach(function (key) {
|
||||
var value = _this.options_[key];
|
||||
|
||||
if (isNumber(value)) {
|
||||
_this[key + 'Event_'] = 'timeupdate';
|
||||
} else if (hasNoWhitespace(value)) {
|
||||
_this[key + 'Event_'] = value; // An overlay MUST have a start option. Otherwise, it's pointless.
|
||||
} else if (key === 'start') {
|
||||
throw new Error('invalid "start" option; expected number or string');
|
||||
}
|
||||
}); // video.js does not like components with multiple instances binding
|
||||
// events to the player because it tracks them at the player level,
|
||||
// not at the level of the object doing the binding. This could also be
|
||||
// solved with Function.prototype.bind (but not videojs.bind because of
|
||||
// its GUID magic), but the anonymous function approach avoids any issues
|
||||
// caused by crappy libraries clobbering Function.prototype.bind.
|
||||
// - https://github.com/videojs/video.js/issues/3097
|
||||
|
||||
['endListener_', 'rewindListener_', 'startListener_'].forEach(function (name$$1) {
|
||||
_this[name$$1] = function (e) {
|
||||
return Overlay.prototype[name$$1].call(_assertThisInitialized(_assertThisInitialized(_this)), e);
|
||||
};
|
||||
}); // If the start event is a timeupdate, we need to watch for rewinds (i.e.,
|
||||
// when the user seeks backward).
|
||||
|
||||
if (_this.startEvent_ === 'timeupdate') {
|
||||
_this.on(player, 'timeupdate', _this.rewindListener_);
|
||||
}
|
||||
|
||||
_this.debug("created, listening to \"" + _this.startEvent_ + "\" for \"start\" and \"" + (_this.endEvent_ || 'nothing') + "\" for \"end\"");
|
||||
|
||||
_this.hide();
|
||||
|
||||
return _this;
|
||||
}
|
||||
|
||||
var _proto = Overlay.prototype;
|
||||
|
||||
_proto.createEl = function createEl() {
|
||||
var options = this.options_;
|
||||
var content = options.content;
|
||||
var background = options.showBackground ? 'vjs-overlay-background' : 'vjs-overlay-no-background';
|
||||
var el = dom.createEl('div', {
|
||||
className: "\n vjs-overlay\n vjs-overlay-" + options.align + "\n " + options.class + "\n " + background + "\n vjs-hidden\n "
|
||||
});
|
||||
|
||||
if (typeof content === 'string') {
|
||||
el.innerHTML = content;
|
||||
} else if (content instanceof window.DocumentFragment) {
|
||||
el.appendChild(content);
|
||||
} else {
|
||||
dom.appendContent(el, content);
|
||||
}
|
||||
|
||||
return el;
|
||||
};
|
||||
/**
|
||||
* Logs debug errors
|
||||
* @param {...[type]} args [description]
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
|
||||
|
||||
_proto.debug = function debug() {
|
||||
if (!this.options_.debug) {
|
||||
return;
|
||||
}
|
||||
|
||||
var log = videojs.log;
|
||||
var fn = log; // Support `videojs.log.foo` calls.
|
||||
|
||||
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
||||
args[_key] = arguments[_key];
|
||||
}
|
||||
|
||||
if (log.hasOwnProperty(args[0]) && typeof log[args[0]] === 'function') {
|
||||
fn = log[args.shift()];
|
||||
}
|
||||
|
||||
fn.apply(void 0, ["overlay#" + this.id() + ": "].concat(args));
|
||||
};
|
||||
/**
|
||||
* Overrides the inherited method to perform some event binding
|
||||
*
|
||||
* @return {Overlay}
|
||||
*/
|
||||
|
||||
|
||||
_proto.hide = function hide() {
|
||||
_Component.prototype.hide.call(this);
|
||||
|
||||
this.debug('hidden');
|
||||
this.debug("bound `startListener_` to \"" + this.startEvent_ + "\""); // Overlays without an "end" are valid.
|
||||
|
||||
if (this.endEvent_) {
|
||||
this.debug("unbound `endListener_` from \"" + this.endEvent_ + "\"");
|
||||
this.off(this.player(), this.endEvent_, this.endListener_);
|
||||
}
|
||||
|
||||
this.on(this.player(), this.startEvent_, this.startListener_);
|
||||
return this;
|
||||
};
|
||||
/**
|
||||
* Determine whether or not the overlay should hide.
|
||||
*
|
||||
* @param {Number} time
|
||||
* The current time reported by the player.
|
||||
* @param {String} type
|
||||
* An event type.
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
|
||||
_proto.shouldHide_ = function shouldHide_(time, type) {
|
||||
var end = this.options_.end;
|
||||
return isNumber(end) ? time >= end : end === type;
|
||||
};
|
||||
/**
|
||||
* Overrides the inherited method to perform some event binding
|
||||
*
|
||||
* @return {Overlay}
|
||||
*/
|
||||
|
||||
|
||||
_proto.show = function show() {
|
||||
_Component.prototype.show.call(this);
|
||||
|
||||
this.off(this.player(), this.startEvent_, this.startListener_);
|
||||
this.debug('shown');
|
||||
this.debug("unbound `startListener_` from \"" + this.startEvent_ + "\""); // Overlays without an "end" are valid.
|
||||
|
||||
if (this.endEvent_) {
|
||||
this.debug("bound `endListener_` to \"" + this.endEvent_ + "\"");
|
||||
this.on(this.player(), this.endEvent_, this.endListener_);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
/**
|
||||
* Determine whether or not the overlay should show.
|
||||
*
|
||||
* @param {Number} time
|
||||
* The current time reported by the player.
|
||||
* @param {String} type
|
||||
* An event type.
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
|
||||
_proto.shouldShow_ = function shouldShow_(time, type) {
|
||||
var start = this.options_.start;
|
||||
var end = this.options_.end;
|
||||
|
||||
if (isNumber(start)) {
|
||||
if (isNumber(end)) {
|
||||
return time >= start && time < end; // In this case, the start is a number and the end is a string. We need
|
||||
// to check whether or not the overlay has shown since the last seek.
|
||||
} else if (!this.hasShownSinceSeek_) {
|
||||
this.hasShownSinceSeek_ = true;
|
||||
return time >= start;
|
||||
} // In this case, the start is a number and the end is a string, but
|
||||
// the overlay has shown since the last seek. This means that we need
|
||||
// to be sure we aren't re-showing it at a later time than it is
|
||||
// scheduled to appear.
|
||||
|
||||
|
||||
return Math.floor(time) === start;
|
||||
}
|
||||
|
||||
return start === type;
|
||||
};
|
||||
/**
|
||||
* Event listener that can trigger the overlay to show.
|
||||
*
|
||||
* @param {Event} e
|
||||
*/
|
||||
|
||||
|
||||
_proto.startListener_ = function startListener_(e) {
|
||||
var time = this.player().currentTime();
|
||||
|
||||
if (this.shouldShow_(time, e.type)) {
|
||||
this.show();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Event listener that can trigger the overlay to show.
|
||||
*
|
||||
* @param {Event} e
|
||||
*/
|
||||
|
||||
|
||||
_proto.endListener_ = function endListener_(e) {
|
||||
var time = this.player().currentTime();
|
||||
|
||||
if (this.shouldHide_(time, e.type)) {
|
||||
this.hide();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Event listener that can looks for rewinds - that is, backward seeks
|
||||
* and may hide the overlay as needed.
|
||||
*
|
||||
* @param {Event} e
|
||||
*/
|
||||
|
||||
|
||||
_proto.rewindListener_ = function rewindListener_(e) {
|
||||
var time = this.player().currentTime();
|
||||
var previous = this.previousTime_;
|
||||
var start = this.options_.start;
|
||||
var end = this.options_.end; // Did we seek backward?
|
||||
|
||||
if (time < previous) {
|
||||
this.debug('rewind detected'); // The overlay remains visible if two conditions are met: the end value
|
||||
// MUST be an integer and the the current time indicates that the
|
||||
// overlay should NOT be visible.
|
||||
|
||||
if (isNumber(end) && !this.shouldShow_(time)) {
|
||||
this.debug("hiding; " + end + " is an integer and overlay should not show at this time");
|
||||
this.hasShownSinceSeek_ = false;
|
||||
this.hide(); // If the end value is an event name, we cannot reliably decide if the
|
||||
// overlay should still be displayed based solely on time; so, we can
|
||||
// only queue it up for showing if the seek took us to a point before
|
||||
// the start time.
|
||||
} else if (hasNoWhitespace(end) && time < start) {
|
||||
this.debug("hiding; show point (" + start + ") is before now (" + time + ") and end point (" + end + ") is an event");
|
||||
this.hasShownSinceSeek_ = false;
|
||||
// If the start event is a timeupdate, we need to watch for rewinds (i.e.,
|
||||
// when the user seeks backward).
|
||||
if (this.startEvent_ === 'timeupdate') {
|
||||
this.on(player, 'timeupdate', this.rewindListener_);
|
||||
}
|
||||
this.debug(`created, listening to "${this.startEvent_}" for "start" and "${this.endEvent_ || 'nothing'}" for "end"`);
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
createEl() {
|
||||
const options = this.options_;
|
||||
const content = options.content;
|
||||
const background = options.showBackground ? 'vjs-overlay-background' : 'vjs-overlay-no-background';
|
||||
const el = dom.createEl('div', {
|
||||
className: `
|
||||
vjs-overlay
|
||||
vjs-overlay-${options.align}
|
||||
${options.class}
|
||||
${background}
|
||||
vjs-hidden
|
||||
`
|
||||
});
|
||||
if (typeof content === 'string') {
|
||||
el.innerHTML = content;
|
||||
} else if (content instanceof window.DocumentFragment) {
|
||||
el.appendChild(content);
|
||||
} else {
|
||||
dom.appendContent(el, content);
|
||||
}
|
||||
return el;
|
||||
}
|
||||
|
||||
this.previousTime_ = time;
|
||||
/**
|
||||
* Logs debug errors
|
||||
*
|
||||
* @param {...[type]} args [description]
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
debug(...args) {
|
||||
if (!this.options_.debug) {
|
||||
return;
|
||||
}
|
||||
const log = videojs.log;
|
||||
let fn = log;
|
||||
|
||||
// Support `videojs.log.foo` calls.
|
||||
if (log.hasOwnProperty(args[0]) && typeof log[args[0]] === 'function') {
|
||||
fn = log[args.shift()];
|
||||
}
|
||||
fn(...[`overlay#${this.id()}: `, ...args]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the inherited method to perform some event binding
|
||||
*
|
||||
* @return {Overlay}
|
||||
*/
|
||||
hide() {
|
||||
super.hide();
|
||||
this.debug('hidden');
|
||||
this.debug(`bound \`startListener_\` to "${this.startEvent_}"`);
|
||||
|
||||
// Overlays without an "end" are valid.
|
||||
if (this.endEvent_) {
|
||||
this.debug(`unbound \`endListener_\` from "${this.endEvent_}"`);
|
||||
this.off(this.player(), this.endEvent_, this.endListener_);
|
||||
}
|
||||
this.on(this.player(), this.startEvent_, this.startListener_);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether or not the overlay should hide.
|
||||
*
|
||||
* @param {number} time
|
||||
* The current time reported by the player.
|
||||
* @param {string} type
|
||||
* An event type.
|
||||
* @return {boolean}
|
||||
*/
|
||||
shouldHide_(time, type) {
|
||||
const end = this.options_.end;
|
||||
return isNumber(end) ? time >= end : end === type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the inherited method to perform some event binding
|
||||
*
|
||||
* @return {Overlay}
|
||||
*/
|
||||
show() {
|
||||
super.show();
|
||||
this.off(this.player(), this.startEvent_, this.startListener_);
|
||||
this.debug('shown');
|
||||
this.debug(`unbound \`startListener_\` from "${this.startEvent_}"`);
|
||||
|
||||
// Overlays without an "end" are valid.
|
||||
if (this.endEvent_) {
|
||||
this.debug(`bound \`endListener_\` to "${this.endEvent_}"`);
|
||||
this.on(this.player(), this.endEvent_, this.endListener_);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether or not the overlay should show.
|
||||
*
|
||||
* @param {number} time
|
||||
* The current time reported by the player.
|
||||
* @param {string} type
|
||||
* An event type.
|
||||
* @return {boolean}
|
||||
*/
|
||||
shouldShow_(time, type) {
|
||||
const start = this.options_.start;
|
||||
const end = this.options_.end;
|
||||
if (isNumber(start)) {
|
||||
if (isNumber(end)) {
|
||||
return time >= start && time < end;
|
||||
|
||||
// In this case, the start is a number and the end is a string. We need
|
||||
// to check whether or not the overlay has shown since the last seek.
|
||||
} else if (!this.hasShownSinceSeek_) {
|
||||
this.hasShownSinceSeek_ = true;
|
||||
return time >= start;
|
||||
}
|
||||
|
||||
// In this case, the start is a number and the end is a string, but
|
||||
// the overlay has shown since the last seek. This means that we need
|
||||
// to be sure we aren't re-showing it at a later time than it is
|
||||
// scheduled to appear.
|
||||
return Math.floor(time) === start;
|
||||
}
|
||||
return start === type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener that can trigger the overlay to show.
|
||||
*
|
||||
* @param {Event} e
|
||||
*/
|
||||
startListener_(e) {
|
||||
const time = this.player().currentTime();
|
||||
if (this.shouldShow_(time, e.type)) {
|
||||
this.show();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener that can trigger the overlay to show.
|
||||
*
|
||||
* @param {Event} e
|
||||
*/
|
||||
endListener_(e) {
|
||||
const time = this.player().currentTime();
|
||||
if (this.shouldHide_(time, e.type)) {
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener that can looks for rewinds - that is, backward seeks
|
||||
* and may hide the overlay as needed.
|
||||
*
|
||||
* @param {Event} e
|
||||
*/
|
||||
rewindListener_(e) {
|
||||
const time = this.player().currentTime();
|
||||
const previous = this.previousTime_;
|
||||
const start = this.options_.start;
|
||||
const end = this.options_.end;
|
||||
|
||||
// Did we seek backward?
|
||||
if (time < previous) {
|
||||
this.debug('rewind detected');
|
||||
|
||||
// The overlay remains visible if two conditions are met: the end value
|
||||
// MUST be an integer and the the current time indicates that the
|
||||
// overlay should NOT be visible.
|
||||
if (isNumber(end) && !this.shouldShow_(time)) {
|
||||
this.debug(`hiding; ${end} is an integer and overlay should not show at this time`);
|
||||
this.hasShownSinceSeek_ = false;
|
||||
this.hide();
|
||||
|
||||
// If the end value is an event name, we cannot reliably decide if the
|
||||
// overlay should still be displayed based solely on time; so, we can
|
||||
// only queue it up for showing if the seek took us to a point before
|
||||
// the start time.
|
||||
} else if (hasNoWhitespace(end) && time < start) {
|
||||
this.debug(`hiding; show point (${start}) is before now (${time}) and end point (${end}) is an event`);
|
||||
this.hasShownSinceSeek_ = false;
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
this.previousTime_ = time;
|
||||
}
|
||||
}
|
||||
videojs.registerComponent('Overlay', Overlay);
|
||||
return Overlay;
|
||||
};
|
||||
|
||||
return Overlay;
|
||||
}(Component);
|
||||
const Plugin = videojs__default["default"].getPlugin('plugin');
|
||||
const defaults = {
|
||||
align: 'top-left',
|
||||
class: '',
|
||||
content: 'This overlay will show up while the video is playing',
|
||||
debug: false,
|
||||
showBackground: true,
|
||||
attachToControlBar: false,
|
||||
overlays: [{
|
||||
start: 'playing',
|
||||
end: 'paused'
|
||||
}]
|
||||
};
|
||||
|
||||
videojs.registerComponent('Overlay', Overlay);
|
||||
/**
|
||||
* Initialize the plugin.
|
||||
*
|
||||
* @function plugin
|
||||
* @param {Object} [options={}]
|
||||
*/
|
||||
/**
|
||||
* A plugin for handling overlays in the Brightcove Player.
|
||||
*/
|
||||
class OverlayPlugin extends Plugin {
|
||||
/**
|
||||
* Create an Overlay Plugin instance.
|
||||
*
|
||||
* @param {Player} player
|
||||
* A Video.js Player instance.
|
||||
*
|
||||
* @param {Object} [options]
|
||||
* An options object.
|
||||
*/
|
||||
constructor(player, options) {
|
||||
super(player);
|
||||
this.reset(options);
|
||||
}
|
||||
|
||||
var plugin = function plugin(options) {
|
||||
var _this2 = this;
|
||||
|
||||
var settings = videojs.mergeOptions(defaults, options); // De-initialize the plugin if it already has an array of overlays.
|
||||
|
||||
if (Array.isArray(this.overlays_)) {
|
||||
this.overlays_.forEach(function (overlay) {
|
||||
_this2.removeChild(overlay);
|
||||
|
||||
if (_this2.controlBar) {
|
||||
_this2.controlBar.removeChild(overlay);
|
||||
/**
|
||||
* Adds one or more items to the existing list of overlays.
|
||||
*
|
||||
* @param {Object|Array} item
|
||||
* An item (or an array of items) to be added as overlay/s
|
||||
*
|
||||
* @return {Array[Overlay]}
|
||||
* The array of overlay objects that were added
|
||||
*/
|
||||
add(item) {
|
||||
if (!Array.isArray(item)) {
|
||||
item = [item];
|
||||
}
|
||||
const addedOverlays = this.mapOverlays_(item);
|
||||
this.player.overlays_ = this.player.overlays_.concat(addedOverlays);
|
||||
return addedOverlays;
|
||||
}
|
||||
|
||||
overlay.dispose();
|
||||
});
|
||||
/**
|
||||
*
|
||||
* @param {Overlay} item
|
||||
* An item to be removed from the array of overlays
|
||||
*
|
||||
* @throws {Error}
|
||||
* Item to remove must be present in the array of overlays
|
||||
*
|
||||
*/
|
||||
remove(item) {
|
||||
const index = this.player.overlays_.indexOf(item);
|
||||
if (index !== -1) {
|
||||
item.el().parentNode.removeChild(item.el());
|
||||
this.player.overlays_.splice(index, 1);
|
||||
} else {
|
||||
this.player.log.warn('overlay does not exist and cannot be removed');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the array of overlays used for the current video
|
||||
*
|
||||
* @return The array of overlay objects currently used by the plugin
|
||||
*/
|
||||
get() {
|
||||
return this.player.overlays_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the overlay options
|
||||
*
|
||||
* @param {Object} [options]
|
||||
* An options object.
|
||||
*/
|
||||
reset(options) {
|
||||
this.clearOverlays_();
|
||||
|
||||
// Use merge function based on video.js version.
|
||||
const merge = videojs__default["default"].obj && videojs__default["default"].obj.merge || videojs__default["default"].mergeOptions;
|
||||
this.options = merge(defaults, options);
|
||||
const overlays = this.options.overlays;
|
||||
|
||||
// We don't want to keep the original array of overlay options around
|
||||
// because it doesn't make sense to pass it to each Overlay component.
|
||||
delete this.options.overlays;
|
||||
this.player.overlays_ = this.mapOverlays_(overlays);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes the plugin
|
||||
*/
|
||||
dispose() {
|
||||
this.clearOverlays_();
|
||||
delete this.player.overlays_;
|
||||
super.dispose();
|
||||
}
|
||||
clearOverlays_() {
|
||||
// Remove child components
|
||||
if (Array.isArray(this.player.overlays_)) {
|
||||
this.player.overlays_.forEach(overlay => {
|
||||
this.player.removeChild(overlay);
|
||||
if (this.player.controlBar) {
|
||||
this.player.controlBar.removeChild(overlay);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
mapOverlays_(items) {
|
||||
return items.map(o => {
|
||||
const mergeOptions = videojs__default["default"].mergeOptions(this.options, o);
|
||||
const attachToControlBar = typeof mergeOptions.attachToControlBar === 'string' || mergeOptions.attachToControlBar === true;
|
||||
if (!this.player.controls() || !this.player.controlBar) {
|
||||
return this.player.addChild('overlay', mergeOptions);
|
||||
}
|
||||
if (attachToControlBar && mergeOptions.align.indexOf('bottom') !== -1) {
|
||||
let referenceChild = this.player.controlBar.children()[0];
|
||||
if (this.player.controlBar.getChild(mergeOptions.attachToControlBar) !== undefined) {
|
||||
referenceChild = this.player.controlBar.getChild(mergeOptions.attachToControlBar);
|
||||
}
|
||||
if (referenceChild) {
|
||||
const referenceChildIndex = this.player.controlBar.children().indexOf(referenceChild);
|
||||
const controlBarChild = this.player.controlBar.addChild('overlay', mergeOptions, referenceChildIndex);
|
||||
return controlBarChild;
|
||||
}
|
||||
}
|
||||
const playerChild = this.player.addChild('overlay', mergeOptions);
|
||||
this.player.el().insertBefore(playerChild.el(), this.player.controlBar.el());
|
||||
return playerChild;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var overlays = settings.overlays; // We don't want to keep the original array of overlay options around
|
||||
// because it doesn't make sense to pass it to each Overlay component.
|
||||
var version = "4.0.0";
|
||||
|
||||
delete settings.overlays;
|
||||
this.overlays_ = overlays.map(function (o) {
|
||||
var mergeOptions = videojs.mergeOptions(settings, o);
|
||||
var attachToControlBar = typeof mergeOptions.attachToControlBar === 'string' || mergeOptions.attachToControlBar === true;
|
||||
initOverlayComponent(videojs__default["default"]);
|
||||
OverlayPlugin.VERSION = version;
|
||||
videojs__default["default"].registerPlugin('overlay', OverlayPlugin);
|
||||
|
||||
if (!_this2.controls() || !_this2.controlBar) {
|
||||
return _this2.addChild('overlay', mergeOptions);
|
||||
}
|
||||
return OverlayPlugin;
|
||||
|
||||
if (attachToControlBar && mergeOptions.align.indexOf('bottom') !== -1) {
|
||||
var referenceChild = _this2.controlBar.children()[0];
|
||||
|
||||
if (_this2.controlBar.getChild(mergeOptions.attachToControlBar) !== undefined) {
|
||||
referenceChild = _this2.controlBar.getChild(mergeOptions.attachToControlBar);
|
||||
}
|
||||
|
||||
if (referenceChild) {
|
||||
var referenceChildIndex = _this2.controlBar.children().indexOf(referenceChild);
|
||||
|
||||
var controlBarChild = _this2.controlBar.addChild('overlay', mergeOptions, referenceChildIndex);
|
||||
|
||||
return controlBarChild;
|
||||
}
|
||||
}
|
||||
|
||||
var playerChild = _this2.addChild('overlay', mergeOptions);
|
||||
|
||||
_this2.el().insertBefore(playerChild.el(), _this2.controlBar.el());
|
||||
|
||||
return playerChild;
|
||||
});
|
||||
};
|
||||
|
||||
plugin.VERSION = version;
|
||||
registerPlugin('overlay', plugin);
|
||||
|
||||
module.exports = plugin;
|
||||
}));
|
||||
|
||||
@ -1 +1,7 @@
|
||||
.video-js .vjs-overlay{color:#fff;position:absolute;text-align:center}.video-js .vjs-overlay-no-background{max-width:33%}.video-js .vjs-overlay-background{background-color:#646464;background-color:rgba(255,255,255,0.4);border-radius:3px;padding:10px;width:33%}.video-js .vjs-overlay-top-left{top:5px;left:5px}.video-js .vjs-overlay-top{left:50%;margin-left:-16.5%;top:5px}.video-js .vjs-overlay-top-right{right:5px;top:5px}.video-js .vjs-overlay-right{right:5px;top:50%;transform:translateY(-50%)}.video-js .vjs-overlay-bottom-right{bottom:3.5em;right:5px}.video-js .vjs-overlay-bottom{bottom:3.5em;left:50%;margin-left:-16.5%}.video-js .vjs-overlay-bottom-left{bottom:3.5em;left:5px}.video-js .vjs-overlay-left{left:5px;top:50%;transform:translateY(-50%)}.video-js .vjs-overlay-center{left:50%;margin-left:-16.5%;top:50%;transform:translateY(-50%)}.video-js .vjs-no-flex .vjs-overlay-left,.video-js .vjs-no-flex .vjs-overlay-center,.video-js .vjs-no-flex .vjs-overlay-right{margin-top:-15px}
|
||||
/**
|
||||
* Skipped minification because the original files appears to be already minified.
|
||||
* Original file: /npm/videojs-overlay@4.0.0/dist/videojs-overlay.css
|
||||
*
|
||||
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
|
||||
*/
|
||||
.video-js .vjs-overlay{color:#fff;position:absolute;text-align:center}.video-js .vjs-overlay-no-background{max-width:33%}.video-js .vjs-overlay-background{background-color:#646464;background-color:hsla(0,0%,100%,.4);border-radius:3px;padding:10px;width:33%}.video-js .vjs-overlay-top-left{top:5px;left:5px}.video-js .vjs-overlay-top{left:50%;margin-left:-16.5%;top:5px}.video-js .vjs-overlay-top-right{right:5px;top:5px}.video-js .vjs-overlay-right{right:5px;top:50%;transform:translateY(-50%)}.video-js .vjs-overlay-bottom-right{bottom:3.5em;right:5px}.video-js .vjs-overlay-bottom{bottom:3.5em;left:50%;margin-left:-16.5%}.video-js .vjs-overlay-bottom-left{bottom:3.5em;left:5px}.video-js .vjs-overlay-left{left:5px;top:50%;transform:translateY(-50%)}.video-js .vjs-overlay-center{left:50%;margin-left:-16.5%;top:50%;transform:translateY(-50%)}.video-js .vjs-no-flex .vjs-overlay-left,.video-js .vjs-no-flex .vjs-overlay-center,.video-js .vjs-no-flex .vjs-overlay-right{margin-top:-15px}/*# sourceMappingURL=videojs-overlay.css.map */
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -98,42 +98,43 @@
|
||||
}
|
||||
|
||||
var player = videojs('player', config);
|
||||
player.ready(function() {
|
||||
if(playerConfig.logo.image.length != 0) {
|
||||
var overlay = null;
|
||||
|
||||
var imgTag = new Image();
|
||||
imgTag.onLoad = function () {
|
||||
imgTag.setAttribute('width', this.width);
|
||||
imgTag.setAttribute('height'.this.height);
|
||||
};
|
||||
imgTag.src = playerConfig.logo.image + '?' + Math.random();
|
||||
if(playerConfig.logo.image.length != 0) {
|
||||
var overlay = null;
|
||||
|
||||
if (playerConfig.logo.link.length !== 0) {
|
||||
var aTag = document.createElement('a');
|
||||
aTag.setAttribute('href', playerConfig.logo.link);
|
||||
aTag.setAttribute('target', '_blank');
|
||||
aTag.appendChild(imgTag);
|
||||
overlay = aTag.outerHTML;
|
||||
} else {
|
||||
overlay = imgTag.outerHTML;
|
||||
}
|
||||
var imgTag = new Image();
|
||||
imgTag.onLoad = function () {
|
||||
imgTag.setAttribute('width', this.width);
|
||||
imgTag.setAttribute('height'.this.height);
|
||||
};
|
||||
imgTag.src = playerConfig.logo.image + '?' + Math.random();
|
||||
|
||||
player.overlay({
|
||||
align: playerConfig.logo.position,
|
||||
overlays: [
|
||||
{
|
||||
showBackground: false,
|
||||
content: overlay,
|
||||
start: 'playing',
|
||||
end: 'pause',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
player.license(playerConfig.license);
|
||||
if (playerConfig.logo.link.length !== 0) {
|
||||
var aTag = document.createElement('a');
|
||||
aTag.setAttribute('href', playerConfig.logo.link);
|
||||
aTag.setAttribute('target', '_blank');
|
||||
aTag.appendChild(imgTag);
|
||||
overlay = aTag.outerHTML;
|
||||
} else {
|
||||
overlay = imgTag.outerHTML;
|
||||
}
|
||||
|
||||
player.overlay({
|
||||
align: playerConfig.logo.position,
|
||||
overlays: [
|
||||
{
|
||||
showBackground: false,
|
||||
content: overlay,
|
||||
start: 'play',
|
||||
end: 'pause',
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
player.ready(function() {
|
||||
player.license(playerConfig.license);
|
||||
|
||||
if (autoplay === true) {
|
||||
// https://videojs.com/blog/autoplay-best-practices-with-video-js/
|
||||
player.play();
|
||||
|
||||
@ -73,7 +73,7 @@ export default function Player({
|
||||
{
|
||||
showBackground: false,
|
||||
content: overlay,
|
||||
start: 'playing',
|
||||
start: 'play',
|
||||
end: 'pause',
|
||||
},
|
||||
],
|
||||
|
||||
1
src/misc/Player/videojs-overlay.css
Normal file
1
src/misc/Player/videojs-overlay.css
Normal file
@ -0,0 +1 @@
|
||||
.video-js .vjs-overlay{color:#fff;position:absolute;text-align:center}.video-js .vjs-overlay-no-background{max-width:33%}.video-js .vjs-overlay-background{background-color:#646464;background-color:hsla(0,0%,100%,.4);border-radius:3px;padding:10px;width:33%}.video-js .vjs-overlay-top-left{top:5px;left:5px}.video-js .vjs-overlay-top{left:50%;margin-left:-16.5%;top:5px}.video-js .vjs-overlay-top-right{right:5px;top:5px}.video-js .vjs-overlay-right{right:5px;top:50%;transform:translateY(-50%)}.video-js .vjs-overlay-bottom-right{bottom:3.5em;right:5px}.video-js .vjs-overlay-bottom{bottom:3.5em;left:50%;margin-left:-16.5%}.video-js .vjs-overlay-bottom-left{bottom:3.5em;left:5px}.video-js .vjs-overlay-left{left:5px;top:50%;transform:translateY(-50%)}.video-js .vjs-overlay-center{left:50%;margin-left:-16.5%;top:50%;transform:translateY(-50%)}.video-js .vjs-no-flex .vjs-overlay-left,.video-js .vjs-no-flex .vjs-overlay-center,.video-js .vjs-no-flex .vjs-overlay-right{margin-top:-15px}
|
||||
411
src/misc/Player/videojs-overlay.es.js
Normal file
411
src/misc/Player/videojs-overlay.es.js
Normal file
@ -0,0 +1,411 @@
|
||||
/*! @name videojs-overlay @version 4.0.0 @license Apache-2.0 */
|
||||
import videojs from 'video.js';
|
||||
import window from 'global/window';
|
||||
|
||||
const initOverlayComponent = videojs => {
|
||||
const Component = videojs.getComponent('Component');
|
||||
const dom = videojs.dom || videojs;
|
||||
|
||||
/**
|
||||
* Whether the value is a `Number`.
|
||||
*
|
||||
* Both `Infinity` and `-Infinity` are accepted, but `NaN` is not.
|
||||
*
|
||||
* @param {Number} n
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
/* eslint-disable no-self-compare */
|
||||
const isNumber = n => typeof n === 'number' && n === n;
|
||||
/* eslint-enable no-self-compare */
|
||||
|
||||
/**
|
||||
* Whether a value is a string with no whitespace.
|
||||
*
|
||||
* @param {string} s
|
||||
* @return {boolean}
|
||||
*/
|
||||
const hasNoWhitespace = s => typeof s === 'string' && /^\S+$/.test(s);
|
||||
|
||||
/**
|
||||
* Overlay component.
|
||||
*
|
||||
* @class Overlay
|
||||
* @extends {videojs.Component}
|
||||
*/
|
||||
class Overlay extends Component {
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
['start', 'end'].forEach(key => {
|
||||
const value = this.options_[key];
|
||||
if (isNumber(value)) {
|
||||
this[key + 'Event_'] = 'timeupdate';
|
||||
} else if (hasNoWhitespace(value)) {
|
||||
this[key + 'Event_'] = value;
|
||||
|
||||
// An overlay MUST have a start option. Otherwise, it's pointless.
|
||||
} else if (key === 'start') {
|
||||
throw new Error('invalid "start" option; expected number or string');
|
||||
}
|
||||
});
|
||||
|
||||
// video.js does not like components with multiple instances binding
|
||||
// events to the player because it tracks them at the player level,
|
||||
// not at the level of the object doing the binding. This could also be
|
||||
// solved with Function.prototype.bind (but not videojs.bind because of
|
||||
// its GUID magic), but the anonymous function approach avoids any issues
|
||||
// caused by crappy libraries clobbering Function.prototype.bind.
|
||||
// - https://github.com/videojs/video.js/issues/3097
|
||||
['endListener_', 'rewindListener_', 'startListener_'].forEach(name => {
|
||||
this[name] = e => Overlay.prototype[name].call(this, e);
|
||||
});
|
||||
|
||||
// If the start event is a timeupdate, we need to watch for rewinds (i.e.,
|
||||
// when the user seeks backward).
|
||||
if (this.startEvent_ === 'timeupdate') {
|
||||
this.on(player, 'timeupdate', this.rewindListener_);
|
||||
}
|
||||
this.debug(`created, listening to "${this.startEvent_}" for "start" and "${this.endEvent_ || 'nothing'}" for "end"`);
|
||||
this.hide();
|
||||
}
|
||||
createEl() {
|
||||
const options = this.options_;
|
||||
const content = options.content;
|
||||
const background = options.showBackground ? 'vjs-overlay-background' : 'vjs-overlay-no-background';
|
||||
const el = dom.createEl('div', {
|
||||
className: `
|
||||
vjs-overlay
|
||||
vjs-overlay-${options.align}
|
||||
${options.class}
|
||||
${background}
|
||||
vjs-hidden
|
||||
`
|
||||
});
|
||||
if (typeof content === 'string') {
|
||||
el.innerHTML = content;
|
||||
} else if (content instanceof window.DocumentFragment) {
|
||||
el.appendChild(content);
|
||||
} else {
|
||||
dom.appendContent(el, content);
|
||||
}
|
||||
return el;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs debug errors
|
||||
*
|
||||
* @param {...[type]} args [description]
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
debug(...args) {
|
||||
if (!this.options_.debug) {
|
||||
return;
|
||||
}
|
||||
const log = videojs.log;
|
||||
let fn = log;
|
||||
|
||||
// Support `videojs.log.foo` calls.
|
||||
if (log.hasOwnProperty(args[0]) && typeof log[args[0]] === 'function') {
|
||||
fn = log[args.shift()];
|
||||
}
|
||||
fn(...[`overlay#${this.id()}: `, ...args]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the inherited method to perform some event binding
|
||||
*
|
||||
* @return {Overlay}
|
||||
*/
|
||||
hide() {
|
||||
super.hide();
|
||||
this.debug('hidden');
|
||||
this.debug(`bound \`startListener_\` to "${this.startEvent_}"`);
|
||||
|
||||
// Overlays without an "end" are valid.
|
||||
if (this.endEvent_) {
|
||||
this.debug(`unbound \`endListener_\` from "${this.endEvent_}"`);
|
||||
this.off(this.player(), this.endEvent_, this.endListener_);
|
||||
}
|
||||
this.on(this.player(), this.startEvent_, this.startListener_);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether or not the overlay should hide.
|
||||
*
|
||||
* @param {number} time
|
||||
* The current time reported by the player.
|
||||
* @param {string} type
|
||||
* An event type.
|
||||
* @return {boolean}
|
||||
*/
|
||||
shouldHide_(time, type) {
|
||||
const end = this.options_.end;
|
||||
return isNumber(end) ? time >= end : end === type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the inherited method to perform some event binding
|
||||
*
|
||||
* @return {Overlay}
|
||||
*/
|
||||
show() {
|
||||
super.show();
|
||||
this.off(this.player(), this.startEvent_, this.startListener_);
|
||||
this.debug('shown');
|
||||
this.debug(`unbound \`startListener_\` from "${this.startEvent_}"`);
|
||||
|
||||
// Overlays without an "end" are valid.
|
||||
if (this.endEvent_) {
|
||||
this.debug(`bound \`endListener_\` to "${this.endEvent_}"`);
|
||||
this.on(this.player(), this.endEvent_, this.endListener_);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether or not the overlay should show.
|
||||
*
|
||||
* @param {number} time
|
||||
* The current time reported by the player.
|
||||
* @param {string} type
|
||||
* An event type.
|
||||
* @return {boolean}
|
||||
*/
|
||||
shouldShow_(time, type) {
|
||||
const start = this.options_.start;
|
||||
const end = this.options_.end;
|
||||
if (isNumber(start)) {
|
||||
if (isNumber(end)) {
|
||||
return time >= start && time < end;
|
||||
|
||||
// In this case, the start is a number and the end is a string. We need
|
||||
// to check whether or not the overlay has shown since the last seek.
|
||||
} else if (!this.hasShownSinceSeek_) {
|
||||
this.hasShownSinceSeek_ = true;
|
||||
return time >= start;
|
||||
}
|
||||
|
||||
// In this case, the start is a number and the end is a string, but
|
||||
// the overlay has shown since the last seek. This means that we need
|
||||
// to be sure we aren't re-showing it at a later time than it is
|
||||
// scheduled to appear.
|
||||
return Math.floor(time) === start;
|
||||
}
|
||||
return start === type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener that can trigger the overlay to show.
|
||||
*
|
||||
* @param {Event} e
|
||||
*/
|
||||
startListener_(e) {
|
||||
const time = this.player().currentTime();
|
||||
if (this.shouldShow_(time, e.type)) {
|
||||
this.show();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener that can trigger the overlay to show.
|
||||
*
|
||||
* @param {Event} e
|
||||
*/
|
||||
endListener_(e) {
|
||||
const time = this.player().currentTime();
|
||||
if (this.shouldHide_(time, e.type)) {
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener that can looks for rewinds - that is, backward seeks
|
||||
* and may hide the overlay as needed.
|
||||
*
|
||||
* @param {Event} e
|
||||
*/
|
||||
rewindListener_(e) {
|
||||
const time = this.player().currentTime();
|
||||
const previous = this.previousTime_;
|
||||
const start = this.options_.start;
|
||||
const end = this.options_.end;
|
||||
|
||||
// Did we seek backward?
|
||||
if (time < previous) {
|
||||
this.debug('rewind detected');
|
||||
|
||||
// The overlay remains visible if two conditions are met: the end value
|
||||
// MUST be an integer and the the current time indicates that the
|
||||
// overlay should NOT be visible.
|
||||
if (isNumber(end) && !this.shouldShow_(time)) {
|
||||
this.debug(`hiding; ${end} is an integer and overlay should not show at this time`);
|
||||
this.hasShownSinceSeek_ = false;
|
||||
this.hide();
|
||||
|
||||
// If the end value is an event name, we cannot reliably decide if the
|
||||
// overlay should still be displayed based solely on time; so, we can
|
||||
// only queue it up for showing if the seek took us to a point before
|
||||
// the start time.
|
||||
} else if (hasNoWhitespace(end) && time < start) {
|
||||
this.debug(`hiding; show point (${start}) is before now (${time}) and end point (${end}) is an event`);
|
||||
this.hasShownSinceSeek_ = false;
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
this.previousTime_ = time;
|
||||
}
|
||||
}
|
||||
videojs.registerComponent('Overlay', Overlay);
|
||||
return Overlay;
|
||||
};
|
||||
|
||||
const Plugin = videojs.getPlugin('plugin');
|
||||
const defaults = {
|
||||
align: 'top-left',
|
||||
class: '',
|
||||
content: 'This overlay will show up while the video is playing',
|
||||
debug: false,
|
||||
showBackground: true,
|
||||
attachToControlBar: false,
|
||||
overlays: [{
|
||||
start: 'playing',
|
||||
end: 'paused'
|
||||
}]
|
||||
};
|
||||
|
||||
/**
|
||||
* A plugin for handling overlays in the Brightcove Player.
|
||||
*/
|
||||
class OverlayPlugin extends Plugin {
|
||||
/**
|
||||
* Create an Overlay Plugin instance.
|
||||
*
|
||||
* @param {Player} player
|
||||
* A Video.js Player instance.
|
||||
*
|
||||
* @param {Object} [options]
|
||||
* An options object.
|
||||
*/
|
||||
constructor(player, options) {
|
||||
super(player);
|
||||
this.reset(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds one or more items to the existing list of overlays.
|
||||
*
|
||||
* @param {Object|Array} item
|
||||
* An item (or an array of items) to be added as overlay/s
|
||||
*
|
||||
* @return {Array[Overlay]}
|
||||
* The array of overlay objects that were added
|
||||
*/
|
||||
add(item) {
|
||||
if (!Array.isArray(item)) {
|
||||
item = [item];
|
||||
}
|
||||
const addedOverlays = this.mapOverlays_(item);
|
||||
this.player.overlays_ = this.player.overlays_.concat(addedOverlays);
|
||||
return addedOverlays;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Overlay} item
|
||||
* An item to be removed from the array of overlays
|
||||
*
|
||||
* @throws {Error}
|
||||
* Item to remove must be present in the array of overlays
|
||||
*
|
||||
*/
|
||||
remove(item) {
|
||||
const index = this.player.overlays_.indexOf(item);
|
||||
if (index !== -1) {
|
||||
item.el().parentNode.removeChild(item.el());
|
||||
this.player.overlays_.splice(index, 1);
|
||||
} else {
|
||||
this.player.log.warn('overlay does not exist and cannot be removed');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the array of overlays used for the current video
|
||||
*
|
||||
* @return The array of overlay objects currently used by the plugin
|
||||
*/
|
||||
get() {
|
||||
return this.player.overlays_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the overlay options
|
||||
*
|
||||
* @param {Object} [options]
|
||||
* An options object.
|
||||
*/
|
||||
reset(options) {
|
||||
this.clearOverlays_();
|
||||
|
||||
// Use merge function based on video.js version.
|
||||
const merge = videojs.obj && videojs.obj.merge || videojs.mergeOptions;
|
||||
this.options = merge(defaults, options);
|
||||
const overlays = this.options.overlays;
|
||||
|
||||
// We don't want to keep the original array of overlay options around
|
||||
// because it doesn't make sense to pass it to each Overlay component.
|
||||
delete this.options.overlays;
|
||||
this.player.overlays_ = this.mapOverlays_(overlays);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes the plugin
|
||||
*/
|
||||
dispose() {
|
||||
this.clearOverlays_();
|
||||
delete this.player.overlays_;
|
||||
super.dispose();
|
||||
}
|
||||
clearOverlays_() {
|
||||
// Remove child components
|
||||
if (Array.isArray(this.player.overlays_)) {
|
||||
this.player.overlays_.forEach(overlay => {
|
||||
this.player.removeChild(overlay);
|
||||
if (this.player.controlBar) {
|
||||
this.player.controlBar.removeChild(overlay);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
mapOverlays_(items) {
|
||||
return items.map(o => {
|
||||
const mergeOptions = videojs.mergeOptions(this.options, o);
|
||||
const attachToControlBar = typeof mergeOptions.attachToControlBar === 'string' || mergeOptions.attachToControlBar === true;
|
||||
if (!this.player.controls() || !this.player.controlBar) {
|
||||
return this.player.addChild('overlay', mergeOptions);
|
||||
}
|
||||
if (attachToControlBar && mergeOptions.align.indexOf('bottom') !== -1) {
|
||||
let referenceChild = this.player.controlBar.children()[0];
|
||||
if (this.player.controlBar.getChild(mergeOptions.attachToControlBar) !== undefined) {
|
||||
referenceChild = this.player.controlBar.getChild(mergeOptions.attachToControlBar);
|
||||
}
|
||||
if (referenceChild) {
|
||||
const referenceChildIndex = this.player.controlBar.children().indexOf(referenceChild);
|
||||
const controlBarChild = this.player.controlBar.addChild('overlay', mergeOptions, referenceChildIndex);
|
||||
return controlBarChild;
|
||||
}
|
||||
}
|
||||
const playerChild = this.player.addChild('overlay', mergeOptions);
|
||||
this.player.el().insertBefore(playerChild.el(), this.player.controlBar.el());
|
||||
return playerChild;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var version = "4.0.0";
|
||||
|
||||
initOverlayComponent(videojs);
|
||||
OverlayPlugin.VERSION = version;
|
||||
videojs.registerPlugin('overlay', OverlayPlugin);
|
||||
|
||||
export { OverlayPlugin as default };
|
||||
@ -3,11 +3,11 @@ import React from 'react';
|
||||
import Grid from '@mui/material/Grid';
|
||||
|
||||
import videojs from 'video.js';
|
||||
import 'videojs-overlay';
|
||||
import overlay from './videojs-overlay.es.js';
|
||||
import 'video.js/dist/video-js.min.css';
|
||||
import './video-js-skin-internal.min.css';
|
||||
import './video-js-skin-public.min.css';
|
||||
import 'videojs-overlay/dist/videojs-overlay.css';
|
||||
import './videojs-overlay.css';
|
||||
|
||||
export default function VideoJS({ type = 'videojs-internal', options = {}, onReady = null }) {
|
||||
const videoRef = React.useRef(null);
|
||||
@ -28,6 +28,8 @@ export default function VideoJS({ type = 'videojs-internal', options = {}, onRea
|
||||
const videoElement = videoRef.current;
|
||||
if (!videoElement) return;
|
||||
|
||||
videojs.registerPlugin('overlay', overlay);
|
||||
|
||||
const player = (playerRef.current = videojs(videoElement, options, () => {
|
||||
onReady && onReady(player);
|
||||
}));
|
||||
|
||||
@ -11999,10 +11999,10 @@ videojs-font@4.2.0:
|
||||
resolved "https://registry.yarnpkg.com/videojs-font/-/videojs-font-4.2.0.tgz#fbce803d347c565816e296f527e208dc65c9f235"
|
||||
integrity sha512-YPq+wiKoGy2/M7ccjmlvwi58z2xsykkkfNMyIg4xb7EZQQNwB71hcSsB3o75CqQV7/y5lXkXhI/rsGAS7jfEmQ==
|
||||
|
||||
videojs-overlay@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/videojs-overlay/-/videojs-overlay-3.1.0.tgz#d57505d375eca952feeb36e5b33e0a130e3dc9e0"
|
||||
integrity sha512-P863Z4ghWgf7Z4A4uzmHlqIixRb8v5220JuQ4pfb/uorbWSBCt5D+czrp/eTxXXLtSmrSUKn596QswVYZuMzPg==
|
||||
videojs-overlay@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/videojs-overlay/-/videojs-overlay-4.0.0.tgz#aa450b3e6e0a86d9bfc61eff66bbdd9f6ed1f07d"
|
||||
integrity sha512-R+DqPhq8iiyNXUgnXr3ZKWXjLmyiztyvzmND4jr+Fa/MaxN6dMwG7hvqb+la24Qaqh8Jxprnw62vqQ0vc8QoHQ==
|
||||
dependencies:
|
||||
global "^4.3.2"
|
||||
video.js "^6 || ^7 || ^8"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user