引言
上一篇文章:为videojs添加自定义组件 已经介绍了在开源网页视频播放器videojs中添加简单的titleBar组件.
在实际使用中,我们可以发现,在大部分视频网站,都有点击播放下一集和自动连续播放两个选项.这篇文章将通过这两个功能的开发,介绍如何开发control-bar中的组件.
实现Control-Bar中的组件
编写play-next类
这次我们要实现的两个功能都在control-bar上,所以我们在control-bar目录下创建play-next文件.
playNext类中,主要handleClick函数,实现对按钮点击的监听,每当用户点击时,切换到下一个视频资源.
这里的实现方法是通过将player中的资源数组进行循环切换,然后使用资源重新加载方法更换当前播放的资源.
handleClick(event) {
console.log('play-next click');
console.log(this.player_.options_.sources);
let theSrc = this.player_.options_.sources[0];
// 资源数组长度
const len = this.player_.options_.sources.length;
// 更新资源数组
for (let i = 1; i < len; i++) {
this.player_.options_.sources[i - 1] = this.player_.options_.sources[i];
}
this.player_.options_.sources[len - 1] = theSrc;
// 获取下一个资源
theSrc = this.player_.options_.sources[0];
this.player_.pause();
// 重载资源
this.player_.src(theSrc);
this.player_.load();
this.player_.play();
}
其次实现buildCSSClass函数,这里使用video自带的图标
/**
* Builds the default DOM `className`.
*
* @return {string}
* The DOM `className` for this object.
*/
buildCSSClass() {
return 'vjs-icon-next-item';
}
完整类代码如下
import Button from '../button.js';
import Component from '../component.js';
import console from 'global/console';
/**
* Button to play the next video
*
* @extends Button
*/
class PlayNext extends Button {
/**
* 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);
// show or hide replay icon
options.replay = options.replay === undefined || options.replay;
}
/**
* Builds the default DOM `className`.
*
* @return {string}
* The DOM `className` for this object.
*/
buildCSSClass() {
return 'vjs-icon-next-item';
}
/**
* This gets called when an `PlayNext` is "clicked". See
* {@link ClickableComponent} for more detailed information on what a click can be.
*
* @param {EventTarget~Event} [event]
* The `keydown`, `tap`, or `click` event that caused this function to be
* called.
*
* @listens tap
* @listens click
*/
handleClick(event) {
console.log('play-next click');
console.log(this.player_.options_.sources);
let theSrc = this.player_.options_.sources[0];
// 资源数组长度
const len = this.player_.options_.sources.length;
// 更新资源数组
for (let i = 1; i < len; i++) {
this.player_.options_.sources[i - 1] = this.player_.options_.sources[i];
}
this.player_.options_.sources[len - 1] = theSrc;
// 获取下一个资源
theSrc = this.player_.options_.sources[0];
this.player_.pause();
// 重载资源
this.player_.src(theSrc);
this.player_.load();
this.player_.play();
}
/**
* This gets called once after the video has ended and the user seeks so that
* we can change the replay button back to a play button.
*
* @param {EventTarget~Event} [event]
* The event that caused this function to run.
*
* @listens Player#seeked
*/
handleSeeked(event) {
console.log('play-next seeked');
}
}
/**
* The text that should display over the `PlayNext`s controls. Added for localization.
*
* @type {string}
* @private
*/
PlayNext.prototype.controlText_ = 'PlayNext';
//在component中注册组件
Component.registerComponent('PlayNext', PlayNext);
export default PlayNext;
编写auto-play-next类
在control-bar目录下创建auto-play-next文件,编写自动连续播放代码.
自动连续播放按钮主要实现点击事件,当用户点击时切换连续播放状态
handleClick(event) {
console.log('auto-play-next click: ' + flag);
if (flag) {
this.addClass('autoplay-off');
this.removeClass('autoplay-on');
console.log('show ' + 'autoplay-off');
this.off(this.player_, 'ended', this.handleEnded); //解除监听事件
} else {
this.addClass('autoplay-on');
this.removeClass('autoplay-off');
console.log('show ' + 'autoplay-on');
this.on(this.player_, 'ended', this.handleEnded); //添加监听事件
}
flag = !flag;
}
其次绑定监听事件,在视频播放结束时播放播放下一个视频
handleEnded(event) {
console.log('play-next ended');
console.log(this.player_.options_.sources);
let theSrc = this.player_.options_.sources[0];
const len = this.player_.options_.sources.length;
for (let i = 1; i < len; i++) {
this.player_.options_.sources[i - 1] = this.player_.options_.sources[i];
}
this.player_.options_.sources[len - 1] = theSrc;
theSrc = this.player_.options_.sources[0];
this.player_.pause();
this.player_.src(theSrc);
this.player_.load();
this.player_.play();
}
auto-play-next完整代码如下
import Button from '../button.js';
import Component from '../component.js';
import console from 'global/console';
let flag = true;
/**
* Button to auto play next
*
* @extends Button
*/
class AutoPlayNext extends Button {
/**
* 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);
// show or hide replay icon
options.replay = options.replay === undefined || options.replay;
// 绑定监听器
this.on(player, 'ended', this.handleEnded);
flag = true;
}
/**
* Builds the default DOM `className`.
*
* @return {string}
* The DOM `className` for this object.
*/
buildCSSClass() {
return 'autoplay-on';
}
/**
* This gets called when an `autoPlaynext` is "clicked". See
* {@link ClickableComponent} for more detailed information on what a click can be.
*
* @param {EventTarget~Event} [event]
* The `keydown`, `tap`, or `click` event that caused this function to be
* called.
*
* @listens tap
* @listens click
*/
handleClick(event) {
console.log('auto-play-next click: ' + flag);
if (flag) {
this.addClass('autoplay-off');
this.removeClass('autoplay-on');
console.log('show ' + 'autoplay-off');
this.off(this.player_, 'ended', this.handleEnded); //解除监听事件
} else {
this.addClass('autoplay-on');
this.removeClass('autoplay-off');
console.log('show ' + 'autoplay-on');
this.on(this.player_, 'ended', this.handleEnded); //添加监听事件
}
flag = !flag;
}
/**
* when the video is ended,play next one
*
* @param {EventTarget~Event} [event]
* The event that caused this function to run.
*
* @listens Player#ended
*/
handleEnded(event) {
console.log('play-next ended');
console.log(this.player_.options_.sources);
let theSrc = this.player_.options_.sources[0];
const len = this.player_.options_.sources.length;
for (let i = 1; i < len; i++) {
this.player_.options_.sources[i - 1] = this.player_.options_.sources[i];
}
this.player_.options_.sources[len - 1] = theSrc;
theSrc = this.player_.options_.sources[0];
this.player_.pause();
this.player_.src(theSrc);
this.player_.load();
this.player_.play();
}
}
/**
* The text that should display over the `PlayNext`s controls. Added for localization.
*
* @type {string}
* @private
*/
AutoPlayNext.prototype.controlText_ = 'autoPlayNext';
Component.registerComponent('autoPlayNext', AutoPlayNext);
export default AutoPlayNext;
修改css样式
为css样式文件中添加auto-play-next按钮的两种状态(一种为启用时,一种为未启用时)
.video-js .autoplay-on{
background-color:rgba(0, 0, 0, 0.4);
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABRFBMVEX///8AqBQApRQAohMAnhIAmhEAlhAAkg8AjQ4AiQ0AhAwAfQoAHQIAqRUAqhUAqhUAqhUAqBQkwTdU4GZT32QjvzYApRRT3mRP2mAAohMAnhIAmhEAlhAAkg8AjQ4AiQ0AhAwAfQoVyiUPyCAAbQYIkhIQzCAPzB8HkhAAAAAADgEASgIAXQIAXQIAAAAAAAAAAABd5W5c5G1O1l9W3mdGzlc5wUpAyFFP12A9xU4zu0T///+e4qdHz1hJ0Vo2vkcttT4wuUEmrzccpC3i4uLj4+Pn5+cVniYosTlEzFUrszz4+PgcqC0SoiMRnyLe3t7m5uYRniIRoSIbqixByVKi16nV1dXr6+sRpSIRoyIRqiIXrygww0ESriPa2toRqCIRtCIUtSUgxjERviIRrSISviMazCsRyCIRsiIR0SIRtiIR2SJwalQ3AAAAMXRSTlMAAAAAAAAAAAAAAAAADHO6zHPd+fnduvn5zMzMzMzMzMy6+flz3fn53RIzg7zMCRYaP+s52AAAAAFiS0dEAIgFHUgAAAAHdElNRQfkDAYDFSM2DmjWAAAA0UlEQVQY02NgQAeMvHz8AlDAz8fLyMAoKCRsCARGQCAiKsjIwCQmbgwHEmJMDMySJqYQYGZuaiHJzMAiZWEJBlbWNpa2UiwMrNJ29g72jk7OLq5u7h7SrAxsMp5e3j6+fv4uAYFBwTJsDOyyIaFh4RFAfmRUVLQsOwOHXExsWByQH5+QkJAox8HAKZ+UnALkpyQDQao8JwOXQlp6ekZARjoYKHAxcCsqZWZmZmWCgbIiNwOPiqpaNhSoa6jwMGhqaevoQoGOtpYmg56+ARLQ1wMAeFUzXuC3XNoAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMDctMTlUMDM6Mzk6MjArMDA6MDCGZw5cAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE5LTAxLTA4VDE2OjA2OjE1KzAwOjAwr9jbcQAAACB0RVh0c29mdHdhcmUAaHR0cHM6Ly9pbWFnZW1hZ2ljay5vcme8zx2dAAAAGHRFWHRUaHVtYjo6RG9jdW1lbnQ6OlBhZ2VzADGn/7svAAAAF3RFWHRUaHVtYjo6SW1hZ2U6OkhlaWdodAAxNh2vXm8AAAAWdEVYdFRodW1iOjpJbWFnZTo6V2lkdGgAMTblAJ7iAAAAGXRFWHRUaHVtYjo6TWltZXR5cGUAaW1hZ2UvcG5nP7JWTgAAABd0RVh0VGh1bWI6Ok1UaW1lADE1NDY5NjM1NzVfAtNDAAAAEHRFWHRUaHVtYjo6U2l6ZQA2MDVC8ZjPjwAAAFh0RVh0VGh1bWI6OlVSSQBmaWxlOi8vL2RhdGEvd3d3cm9vdC93d3cuZWFzeWljb24ubmV0L2Nkbi1pbWcuZWFzeWljb24uY24vZmlsZXMvNTEvNTE0NzcwLnBuZ31F9QcAAAAASUVORK5CYII=');
background-repeat: no-repeat;
width: 20px;
height: 22px;
margin-top:7px;
text-align: center;
}
.video-js .autoplay-off{
background-color: rgba(0,0,0,0.4);
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkDAYDFiX0QJ4gAAAAgklEQVQoz32QwQ1CMQxD7WIhIcQAiJnYgPtf4h9YFnUA9A9t2pQD58TXvFhP5vuJO+JU7NtKsm+aWFjBOzEhoyeAUYMOD4CCQRkcM3Q0qDMGiE4ZZwIY04aCTrUEOKHlDf5viB0mGnVwhTssHFRVwTmUrOL1VR7hTvAPccENCu4D3x+g7FRfDswphQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMC0wNy0xOVQwMzozOToyMCswMDowMIZnDlwAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTktMDEtMDhUMTY6MDU6NTArMDA6MDCSnUEvAAAAIHRFWHRzb2Z0d2FyZQBodHRwczovL2ltYWdlbWFnaWNrLm9yZ7zPHZ0AAAAYdEVYdFRodW1iOjpEb2N1bWVudDo6UGFnZXMAMaf/uy8AAAAXdEVYdFRodW1iOjpJbWFnZTo6SGVpZ2h0ADE2Ha9ebwAAABZ0RVh0VGh1bWI6OkltYWdlOjpXaWR0aAAxNuUAnuIAAAAZdEVYdFRodW1iOjpNaW1ldHlwZQBpbWFnZS9wbmc/slZOAAAAF3RFWHRUaHVtYjo6TVRpbWUAMTU0Njk2MzU1MB1eRU4AAAAQdEVYdFRodW1iOjpTaXplADI4MUIUhcxkAAAAWHRFWHRUaHVtYjo6VVJJAGZpbGU6Ly8vZGF0YS93d3dyb290L3d3dy5lYXN5aWNvbi5uZXQvY2RuLWltZy5lYXN5aWNvbi5jbi9maWxlcy81MS81MTM3MzYucG5nY1FLqAAAAABJRU5ErkJggg==');
background-repeat: no-repeat;
width: 20px;
height: 22px;
margin-top:7px;
text-align: center;
}
在control-bar中配置自定义组件
想要使用自定义组件,需要在control-bar中进行配置.首先在control-bar中import对应文件
之后在control-bar的children数组中添加自己的组件
应用自定义control-bar组件
首先对项目进行重新编译,生成新的dist文件夹.
测试方法与之前的一致,编写一个简单网页,这里在player初始化中声明启用playNext和autoPlayNext组件,同时在资源数组中传入多个值
测试网页代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Video.js | HTML5 Video Player</title>
<link href="C:\Users\KKFORKK\Desktop\example\docs\copycss.css" rel="stylesheet">
<script src="C:\Users\KKFORKK\Desktop\example\dist\video.min.js"></script>
</head>
<body>
<video id="example_video_1" class="video-js" controls preload="none" width="1024" height="768"
poster="http://vjs.zencdn.net/v/oceans.png">
<p class="vjs-no-js">To view this video please enable JavaScript, and consider upgrading to a web
browser that <a href="https://videojs.com/html5-video-support/" target="_blank">
supports HTML5 video</a></p>
</video>
<script>
var player = videojs('example_video_1', {
inactivityTimeout: 2000,
sourcesOrder:true,
controls: true, // 是否显示控制条
preload: 'auto',
autoplay: false,
language: 'zh-CN', // 设置语言
muted: false, // 是否静音
controlBar: { // 设置控制条组件
/* 使用children的形式可以控制每一个控件的位置,以及显示与否 */
children: [
{name: 'playToggle'}, // 播放按钮
{name: 'PlayNext'}, //点击播放下一个按钮
{name: 'currentTimeDisplay'}, // 当前已播放时间
{name: 'progressControl'}, // 播放进度条
{name: 'durationDisplay'}, // 总时间
{name: 'audioTrackButton'},
{ // 倍数播放
name: 'playbackRateMenuButton',
'playbackRates': [0.5, 1, 1.5, 2, 2.5]
},
{
name: 'volumePanel', // 音量控制
inline: false, // 不使用水平方式
},
{name: 'AutoPlayNext'}, //控制是否自动播放下一个
{name: 'FullscreenToggle'} // 全屏
]
},
sources:[ // 视频源,这里使用了音频文件
{
src: 'D:/Music/Aimer - DAWN.mp3',
type: 'audio/mp3',
poster: '//vjs.zencdn.net/v/oceans.png',
title: '000'
},{
src: 'D:/Music/Aimer - Re:far.mp3',
type: 'audio/mp3',
poster: '//vjs.zencdn.net/v/oceans.png',
title: '001'
},{
src: 'D:/Music/Aimer - Re:pray.mp3',
type: 'audio/mp3',
poster: '//vjs.zencdn.net/v/oceans.png',
title: '002'
}
]
}, function (){
console.log('视频可以播放了',this);
});
</script>
</body>
</html>
最后实现效果如下
可以看到我们的组件都正常启用,并且功能运行正常(样式比较丑,大家见谅)
结语
在对videojs中control-bar组件开发,主要运用js监听器以及点击事件的实现.开发的功能比较简单,更为复杂的功能可查看videojs官方提供的文档,以及对源码详细阅读实现.