自定义插件
西瓜视频播放器主张一切设计都是插件,小到一个播放按钮大到一项直播功能支持。想更好的自定义播放器完成自己业务的契合,理解插件机制是非常重要的;
目前有播放器有一套根据播放器生命周期定义的插件机制,内置了一系列的常用API和相关生命周期的回调,让使用这能够专注在插件本身的逻辑上,而不用太多关心插件如何在播放器中安装、卸载,以及播放器的状态相关管理
插件可配置,在实例化播放器的时候根据插件配置对插件进行实例化,并且有相关接口在播放器实例化完成之后安装相关插件,灵活多变,以下是自定义插件机制的相关说明和相关demo说明
播放器插件基类
BasePlugin
基础插件类,有除了(render)以外完整的插件生命周期,其中静态属性pluginName为必须定义的参数,将作为安装存储插件实例的时候的唯一key, 使用demo如下
// demoBasePlugin.js
import { BasePlugin, Events } from 'xgplayer'
export default class DemoBasePlugin extends BasePlugin {
/**
* (必须声明)插件的名称,将作为插件实例的唯一key值
* 该参数还最为播放器上该插件的配置透传key值,例如:
* var p = new player({
* demoBasePlugin: {
* text: '这是插件demoBasePlugin的配置信息'
* }
* })
* 在插件afterCreate之后可以通过this.config.text获取到改配置参数
**/
static get pluginName() {
return 'demoBasePlugin'
}
static get defaultConfig () {
return {
text: '这是插件demoBasePlugin的默认Text'
}
}
constructor (args) {
super(args)
}
afterPlayerInit () {
// TODO 播放器调用start初始化播放源之后的逻辑
}
afterCreate () {
// 在afterCreate中可以加入DOM的事件监听
this.on(Events.PLAY, () => {
console.log('播放播放回调')
})
}
destroy () {
// 播放器销毁的时候一些逻辑
}
}
Plugin
UI类插件基类,继承自BasePlugin,除了具有完善的生命周期回调,还内置了render以及一些dom相关API,使用demo如下:
import { Plugin } from 'xgplayer'
const { POSITIONS } = Plugin
// demoPlugin.js
export default class demoPlugin extends Plugin {
// 插件的名称,将作为插件实例的唯一key值
static get pluginName() {
return 'demoPlugin'
}
static get defaultConfig () {
return {
// 挂载在controls的右侧,如果不指定则默认挂载在播放器根节点上
position: POSITIONS.CONTROLS_RIGHT
}
}
constructor (args) {
super(args)
}
beforePlayerInit () {
// TODO 播放器调用start初始化播放源之前的逻辑
}
afterPlayerInit () {
// TODO 播放器调用start初始化播放源之后的逻辑
}
afterCreate () {
this.icon = this.find('.icon')
this.onIconClick = (e) => {
console.log('class为icon元素点击回调')
}
this.onClick = () => {
console.log('当前插件根节点点击事件')
}
// 对当前插件根节点内部类名为.icon的元素绑定click事件
this.bind('.icon', 'click', this.onIconClick)
// 对当前插件根节点绑定click事件
this.bind('click', this.onClick)
//TODO 插件实例化之后的一些逻辑
}
destroy () {
this.unbind('.icon', 'click', this.onIconClick)
this.unbind('click', this.onClick)
this.icon = null
// 播放器销毁的时候一些逻辑
}
render () {
return `<div class="demo-plugin">这是一个dmeo插件<div class="icon"></div></div>`
}
}
插件使用
根据配置参数将自定义插件注册到播放器上,有两种方式,一种是播放器初始化参数plugins中配置,另一种方式是播放器实例初始化完成之后,调用插件注册接口进行注册
播放器初始化配置
import Player from 'xgplayer'
import DemoBasePlugin from './demoBasePlugin.js'
import DemoPlugin from '../demoPlugin.js'
const player = new Player({
url: '../video/mp4/xgplayer-demo-720p.mp4',
plugins: [DemoBasePlugin], // 配置参数注册插件
})
// 调用接口注册插件
player.registerPlugin(DemoPlugin)
关于保留配置项position
position用于指定UI插件的dom挂载位置,目前定义的位置如下图所示
默认布局
flex布局
- 插件在不指定position,也不指定root参数的情况下,默认挂载在根节点root下;
- ROOT_TOP、ROOT_RIGHT、ROOT_LEFT会在播放器失去焦点的时候自动隐藏
- 手机小屏flex布局下,中间位置自适应,一般中间位置都是进度条
关于保留配置项index
index是一个数字,用于指定UI插件在父节点上插入的位置,数字越小,越靠前,如果这个相等则按照注册顺序插入; index可以通过配置覆盖来达到调整插件顺序的目的
插件生命周期接口
beforeCreate
插件new的时候,但是还未执行其余一系列操作的时候执行
render
继承自BasePlugin不执行该流程 UI插件渲染,非UI插件不执行,该接口支持返回一个结构的字符串,也支持返回一个dom对象,最终会挂载在root或者指定的其他dom节点上
afterCreate
插件实例创建之后回调,此时可以获取所有内置对象,例如this.player, 如果是UI插件则可以获取到当前插件的根节点,例如this.el
onPluginsReady
播放器初始化带有的的所有插件创建完成之后执行,在该流程可以获取到所有播放器上注册的插件实例,可进行插件实例之间相互依赖交互
destory
播放器destroy的之后回调,插件销毁之前执行,播放器销毁的时候,会先依次执行各个插件的destory
beforePlayerInit
播放器执行start初始化播放源之前
afterPlayerInit
播放器执行start逻辑,播放源被初始化之后
内置对象
player[只读]
播放器实例, 在插件内部可以直接通过this.player调用播放器任何API
playerConfig[只读]
播放器初始配置, 在插件内部可以直接通过this. playerConfig获取
pluginName[只读]
插件名称唯一key, 可通过this.name调用,通过注册插件的时候指定name或者插件静态属性获取
root[只读]
当前插件为UI插件,则是该UI的根节点dom, 通过this.root获取,否则为null
内置API
on (event, callback)
说明: 监听播放器事件, 所有通过该API添加的监听事件在destroy的时候会默认off, 不需要再单独调用off
备注:通过该API监听,播放器销毁的时候会默认接触监听,不需要额外在destroy的时候显示的解除事件监听
举例:
this.on(Events.PLAY, () => {
console.log('play')
})
// 多个事件同时监听处理
this.on([Events.ENDED, Events.PAUSE], () => {
console.log('ended or pause')
})
once (event, callback)
说明: 监听播放器事件,只监听一次
备注:通过该API监听,播放器销毁的时候会默认接触监听,不需要额外在destroy的时候显示的解除事件监听
举例:
this.once(Events.PLAY, () => {
console.log('play')
})
off (event, callback)
说明: 解除播放器事件监听
举例:
this.off(Events.PLAY, () => {
console.log('play')
})
// 多个事件同时监听处理
this.off([Events.ENDED, Events.PAUSE], () => {
console.log('ended or pause')
})
offAll ()
说明: 解除当前插件对播放器的所有事件监听
举例:
this.offAll()
emit (event)
说明: 触发自定义事件
举例:
this.emit('customEvent', () => {
console.log('customEvent')
})
plugins()
说明: 返回当前插件的所有子插件实例,通过调用this.registerPlugin注册的所有子插件
举例:
const childPlugins = this.plugins
getPlugin(key)
说明: 根据插件key值,获取插件实例
举例:
const pc = this.getPlugin('pc')
registerPlugin (Plugin, options, name)
- 说明: 在当前插件中注册自插件,如果当前插件为UI插件
- options或者options.root为空,插件dom结构默认挂载在当前插件根节点上;如果指定了
- options.root为dom结构,插件dom结构默认挂载在root下
- name不为空,插件注册之后实例以name为key值存储
- name为空,插件注册之后实例以Plugin.pluginName返回的值为key
- 举例:
// get pluginName() 返回值为 customplugin
import CustomPlugin from './customplugin'
/**
* 注册之后可以根据this.getPlugin('customplugin')得到插件实例
* 子插件dom挂载在当前插件根节点下
*/
const child1 = this.registerPlugin(CustomPlugin)
/**
* 注册之后可以根据this.getPlugin('csplugin')得到插件实例
* 子插件dom挂载在当前插件dom中classNamew为childdiv的dom下
*/
const child = this.registerPlugin(CustomPlugin, {
//以className 为childdiv的div作为父节点
root: this.find('.childdiv'),
//插件配置信息
config: {
disable: false
}, 'csplugin'});
show
说明: 显示当前插件
示例:
// 默认使用block
plugin.show()
// 指定show参数
plugin.show('flex')
hide
- 说明: 隐藏当前插件
find (selector)
说明: 在当前插件根节点下查找,底层使用的querySelector
示例:
// 获取当前UI插件root下类名为.icon的第一个dom
this.icon = this.find('.icon')
// 获取当前UI插件root下tag为li的所有dom
this.lis = this.find('li')
bind (selector, event, handler)
说明: 对符合选择器的dom添加event事件代理,对应的解除事件代理的UI为unbind,可以在destory的时候调用
示例:
// 对当前UI插件根节点下的li a进行事件代理
this.bind('li a', 'click', this.clickHandler)
this.unbind('li a', 'click', this.clickHandler)
// 对当前插件根节点添加事件监听,目标元素为this.el
this.bind('click', this.clickHandler)
this.unbind('click', this.clickHandler)
// 同时对同一选择器的多个事件监听相同的事件代理
this.bind('li a', ['click', 'touched'], this.clickHandler)
this.unbind('li a', ['click', 'touched'], this.clickHandler)
unbind (selector, event, handler)
说明: 对符合选择器的dom解除event事件代理,可以在destory的时候调用
示例: 参考bind说明
setStyle;
@param { string | {[propName: string]: any} } name
@param { any? } value
说明: 对当前UI插件的根节点设置样式
示例:
// 设置单个样式
this.setStyle('height', '40px')
// 设置多个样式单位
this.setStyle({
'height': '40px',
'width': '40px'
})
setAttr (name, value)
说明: 对当前UI插件的根节点设置属性
示例:
// 设置单个样式
this.setAttr('data-url', 'https://ixigua.com')
// 设置多个样式单位
this.setAttr({
'data-id': 1,
'data-name': 'name'
})
setHtml (htmlStr, callback)
说明: 对当前根节点重置html结构
示例:
// 设置单个样式
this.setHtml(`<div class="icon">重置icon</div>`, () => {
console.log('dom重置完成')
})
静态枚举对象列表
Plugin.POSITIONS
插件在节点中挂载的位置position的枚举值,用于指定UI插件的dom挂载位置,具体值列表如下
Plugin.POSITIONS = {
ROOT: 'root', //挂载在根节点上
ROOT_LEFT: 'rootLeft', //挂载在播放器容器的左侧边栏
ROOT_RIGHT: 'rootRight', //挂载在播放器容器的右侧边栏
ROOT_TOP: 'rootTop', //挂载在播放器容器的顶部边栏
CONTROLS_LEFT: 'controlsLeft', //挂载在播放器控制栏的左侧
CONTROLS_RIGHT: 'controlsRight', //挂载在播放器控制栏的右侧
CONTROLS_CENTER: 'controlsCenter' //挂载在播放器控制栏的中间控制条位置
}