Video.js 指南
这些指南涵盖了 Video.js 用户的各种主题
组件
注意:本指南侧重于 Video.js 8+ 版本。它不再提及已在 8.0 版本中移除的 videojs.extend()
方法。请参阅我们的迁移指南获取更多信息!
Video.js 播放器的架构以组件为中心。
Player
类以及所有表示播放器控件和其他 UI 元素的类都继承自 Component
类。这种架构使得以镜像 DOM 的树状结构构建 Video.js 播放器的用户界面变得容易。
什么是组件?
组件是一个 JavaScript 对象,具有以下特点:
- 在几乎所有情况下都关联一个 DOM 元素。
- 与一个
Player
对象关联。 - 能够管理任意数量的子组件。
- 能够监听和触发事件。
- 具有初始化和销毁的生命周期。
有关组件编程接口的更多详细信息,请参阅组件 API 文档。
添加组件
可以使用 new Component()
创建组件实例。
// Creating an instance of a button
var player = videojs('some-video-id');
var Button = videojs.getComponent('Button');
var button = new Button(player, {
clickHandler: function(event) {
videojs.log('Clicked');
}
});
console.log(button.el());
上述代码将输出:
<button class="vjs-control vjs-button" type="button" aria-disabled="false">
<span class="vjs-icon-placeholder" aria-hidden="true"></span>
<span class="vjs-control-text" aria-live="polite"></span>
</button>
请注意,这创建了按钮,但并未将其添加到 DOM 中。将其作为组件的子项添加将使其显示在 DOM 中。
player.getChild('ControlBar').addChild(button);
或者,通过将组件名称传递给 addChild
,可以一步创建并添加组件的新实例。
// Creating an instance of a button and addingit to the player's control bar
var player = videojs('some-video-id');
var button = player.getChild('ControlBar').addChild('button', {
clickHandler: function(event) {
videojs.log('Clicked');
}
});
console.log(button.el());
// will have the same html result as the previous example
按钮应包含文本。默认按钮不显示其文本,但它存在用于屏幕阅读器,并由浏览器显示为工具提示。按钮的文本可以设置为选项:
const myButton = player.getChild('ControlBar').addChild('button', {controlText: 'My button'});
要显示控件文本,请将 vjs-visibile-text
类添加到按钮。
const myButton = player.getChild('ControlBar').addChild('button', {
controlText: 'My button',
className: 'vjs-visible-text'
});
类和控件文本也可以在按钮创建后设置。
myButton.controlText('My button');
myButton.addClass('vjs-visible-text');
当播放器上启用experimentalSvgIcons
选项时,可以使用 setIcon
方法在任何 Component
上添加或替换图标。
您可以将 sandbox/svg-icons.html.example
重命名为 sandbox/svg-icons.html
,然后使用 npm run build
构建 Video.js,并在您选择的浏览器中打开 sandbox/svg-icons.html
,从而查看所有可用图标。
myButton.setIcon('play');
创建组件
Video.js 组件是 ES6 类,可以使用类语法进行扩展并向 Video.js 注册,以便为播放器添加新功能和 UI。
有几个用于创建和注册组件的函数:
videojs.getComponent(String name)
:从 Video.js 中检索组件类。videojs.registerComponent(String name, Function Comp)
:向 Video.js 注册组件类。
此示例创建了一个标题栏组件,作为扩展 Component
的类。
// Get the Component base class from Video.js
const Component = videojs.getComponent('Component');
class TitleBar extends Component {
// The constructor of a component receives two arguments: the
// player it will be associated with and an object of options.
constructor(player, options = {}) {
// It is important to invoke the superclass before anything else,
// to get all the features of components out of the box!
super(player, options);
// If a `text` option was passed in, update the text content of
// the component.
if (options.text) {
this.updateTextContent(options.text);
}
}
// The `createEl` function of a component creates its DOM element.
createEl() {
return videojs.dom.createEl('div', {
// Prefixing classes of elements within a player with "vjs-"
// is a convention used in Video.js.
className: 'vjs-title-bar'
});
}
// This function could be called at any time to update the text
// contents of the component.
updateTextContent(text) {
// If no text was provided, default to "Title Unknown"
if (typeof text !== 'string') {
text = 'Title Unknown';
}
// Use Video.js utility DOM methods to manipulate the content
// of the component's element.
videojs.emptyEl(this.el());
videojs.appendContent(this.el(), text);
}
}
请注意,由于 extend()
函数已被移除,在转译为 ES5 时扩展组件需要使用以下语法。
// My ES5 constructor function extending Component
function MyComponent(arguments) {
Component.call(this, arguments);
}
MyComponent.prototype = Object.create(Component.prototype);
组件创建后,可以注册并在播放器中使用。
// Register the component with Video.js, so it can be used in players.
videojs.registerComponent('TitleBar', TitleBar);
// Create a player.
var player = videojs('my-player');
// Add the TitleBar as a child of the player and provide it some text
// in its options.
player.addChild('TitleBar', {text: 'The Title of The Video!'});
实时示例位于此 JSBin 中。
组件子项
再次,请参阅组件 API 文档以获取有关管理组件结构的完整详细信息。
基本示例
当子组件添加到父组件时,Video.js 会将子组件的元素插入到父组件的元素中。例如,添加一个组件像这样:
// Add a "BigPlayButton" component to the player. Its element will be appended to the player's element.
player.addChild('BigPlayButton');
结果是 DOM 看起来像这样:
<!-- Player Element -->
<div class="video-js">
<!-- BigPlayButton Element -->
<div class="vjs-big-play-button"></div>
</div>
相反,移除子组件将从 DOM 中移除子组件的元素。
player.removeChild('BigPlayButton');
结果是 DOM 看起来像这样:
<!-- Player Element -->
<div class="video-js">
</div>
使用选项
为子构造函数及其子项传递选项。
var player = videojs('some-vid-id');
var Component = videojs.getComponent('Component');
var myComponent = new Component(player);
var myButton = myComponent.addChild('MyButton', {
text: 'Press Me',
buttonChildExample: {
buttonChildOption: true
}
});
在组件初始化时,也可以通过选项添加子项。
注意:如果两个相同类型但需要不同选项的子组件,请包含一个 'name' 键。
// MyComponent is from the above example
var myComp = new MyComponent(player, {
children: ['button', {
name: 'button',
someOtherOption: true
}, {
name: 'button',
someOtherOption: false
}]
});
事件监听
使用 on
var player = videojs('some-player-id');
var Component = videojs.getComponent('Component');
var myComponent = new Component(player);
var myFunc = function() {
var myComponent = this;
console.log('myFunc called');
};
myComponent.on('eventType', myFunc);
myComponent.trigger('eventType');
// logs 'myFunc called'
除非绑定,否则 myFunc
的上下文将是 myComponent
。您可以向另一个元素或组件添加监听器。
var otherComponent = new Component(player);
// myComponent/myFunc is from the above example
myComponent.on(otherComponent.el(), 'eventName', myFunc);
myComponent.on(otherComponent, 'eventName', myFunc);
otherComponent.trigger('eventName');
// logs 'myFunc called' twice
使用 off
var player = videojs('some-player-id');
var Component = videojs.getComponent('Component');
var myComponent = new Component(player);
var myFunc = function() {
var myComponent = this;
console.log('myFunc called');
};
myComponent.on('eventType', myFunc);
myComponent.trigger('eventType');
// logs 'myFunc called'
myComponent.off('eventType', myFunc);
myComponent.trigger('eventType');
// does nothing
如果排除了 myFunc,则该事件类型的所有监听器都将被移除。如果排除了 eventType,则组件的所有监听器都将被移除。您可以使用 off
来移除使用以下方法添加到其他元素或组件的监听器:
myComponent.on(otherComponent...
在这种情况下,事件类型和监听器函数都是必需的。
var otherComponent = new Component(player);
// myComponent/myFunc is from the above example
myComponent.on(otherComponent.el(), 'eventName', myFunc);
myComponent.on(otherComponent, 'eventName', myFunc);
otherComponent.trigger('eventName');
// logs 'myFunc called' twice
myComponent.off(otherComponent.el(), 'eventName', myFunc);
myComponent.off(otherComponent, 'eventName', myFunc);
otherComponent.trigger('eventName');
// does nothing
使用 one
var player = videojs('some-player-id');
var Component = videojs.getComponent('Component');
var myComponent = new Component(player);
var myFunc = function() {
var myComponent = this;
console.log('myFunc called');
};
myComponent.one('eventName', myFunc);
myComponent.trigger('eventName');
// logs 'myFunc called'
myComponent.trigger('eventName');
// does nothing
您还可以向另一个元素或组件添加一个只触发一次的监听器。
var otherComponent = new Component(player);
// myComponent/myFunc is from the above example
myComponent.one(otherComponent.el(), 'eventName', myFunc);
myComponent.one(otherComponent, 'eventName', myFunc);
otherComponent.trigger('eventName');
// logs 'myFunc called' twice
otherComponent.trigger('eventName');
// does nothing
使用 trigger
var player = videojs('some-player-id');
var Component = videojs.getComponent('Component');
var myComponent = new Component(player);
var myFunc = function(data) {
var myComponent = this;
console.log('myFunc called');
console.log(data);
};
myComponent.one('eventName', myFunc);
myComponent.trigger('eventName');
// logs 'myFunc called' and 'undefined'
myComponent.trigger({'type':'eventName'});
// logs 'myFunc called' and 'undefined'
myComponent.trigger('eventName', {data: 'some data'});
// logs 'myFunc called' and "{data: 'some data'}"
myComponent.trigger({'type':'eventName'}, {data: 'some data'});
// logs 'myFunc called' and "{data: 'some data'}"
默认组件树
Video.js 播放器的默认组件结构如下所示:
Player
├── MediaLoader (has no DOM element)
├── PosterImage
├── TextTrackDisplay
├── LoadingSpinner
├── BigPlayButton
├── LiveTracker (has no DOM element)
├─┬ ControlBar
│ ├── PlayToggle
│ ├── VolumePanel
│ ├── CurrentTimeDisplay (hidden by default)
│ ├── TimeDivider (hidden by default)
│ ├── DurationDisplay (hidden by default)
│ ├─┬ ProgressControl (hidden during live playback, except when liveui: true)
│ │ └─┬ SeekBar
│ │ ├── LoadProgressBar
│ │ ├── MouseTimeDisplay
│ │ └── PlayProgressBar
│ ├── LiveDisplay (hidden during VOD playback)
│ ├── SeekToLive (hidden during VOD playback)
│ ├── RemainingTimeDisplay
│ ├── CustomControlSpacer (has no UI)
│ ├── PlaybackRateMenuButton (hidden, unless playback tech supports rate changes)
│ ├── ChaptersButton (hidden, unless there are relevant tracks)
│ ├── DescriptionsButton (hidden, unless there are relevant tracks)
│ ├── SubsCapsButton (hidden, unless there are relevant tracks)
│ ├── AudioTrackButton (hidden, unless there are relevant tracks)
│ ├── PictureInPictureToggle
│ └── FullscreenToggle
├── ErrorDisplay (hidden, until there is an error)
├── TextTrackSettings
└── ResizeManager (hidden)
特定组件详情
播放切换按钮
PlayToggle
有一个选项 replay
,可以显示或隐藏重播图标。默认行为是在视频播放结束后显示重播图标,通过传递 {replay: false}
可以进行设置。
隐藏重播图标的示例:
let player = videojs('myplayer', {
controlBar: {
playToggle: {
replay: false
}
}
});
音量面板
VolumePanel
包含 MuteToggle
和 VolumeControl
组件,如果不支持音量更改,它们将被隐藏。VolumePanel
有一个重要的选项,可以让您的 VolumeControl
垂直显示在 MuteToggle
上方。默认行为是水平的 VolumeControl
({inline: true}
),通过将 VolumePanel
传递 {inline: false}
可以进行设置。
垂直 VolumeControl
的示例:
let player = videojs('myplayer', {
controlBar: {
volumePanel: {
inline: false
}
}
});
文本轨道设置
文本轨道设置组件仅在使用模拟文本轨道时可用。
尺寸管理器
这个新组件负责在播放器尺寸改变时触发一个 playerresize
事件。如果 ResizeObserver 可用或提供了 polyfill,它将使用 ResizeObserver。当使用 ResizeObserver 时,它没有元素。如果 ResizeObserver 不可用,它将回退到 iframe 元素并通过去抖动处理程序监听其尺寸改变事件。
可以像这样传入 ResizeObserver polyfill:
var player = videojs('myplayer', {
resizeManager: {
ResizeObserver: ResizeObserverPoylfill
}
});
要强制使用 iframe 回退,请将 null
作为 ResizeObserver
传入。
var player = videojs('myplayer', {
resizeManager: {
ResizeObserver: null
}
});
ResizeManager 也可以像这样禁用:
var player = videojs('myplayer', {
resizeManager: false
});