西瓜播放器 HTML5 video video.js 播放器 HTML5播放器 mp4 hls hls.js flv flv.js dash dash.js 无缝切换

Plugin

The design of xgplayer is based on plugin system, all of built-in components are developed as plugins, so it is really important for you to learn about the mechanism of plugin for better customizing the player.

Player privides a complete plugin mechanism based on lifecycle callbacks with a series of useful APIs, Therefore you can really focus on your own code.

It's also easy to configurate you plugin, by passing config to player.config. See examples below to learn more:

BasePlugin

BasePlugin is a class of plugin without UI rendering, so it provides full lifecycle except for render

// my-base-plugin.js
import { BasePlugin, Events } from 'xgplayer'
export default class MyBasePlugin extends BasePlugin {
  /**
   * (required) name and identifier of this plugin
   * you can find、configure、deregister plugin by pluginName, for example:
   *
   * const p = new player({
   *   [myBasePlugin]: {
   *     text: 'text for plugin'
   *   }
   * })
   **/
  static get pluginName() {
    return 'myBasePlugin'
  }

  static get defaultConfig () {
    return {
       text: 'default text for plugin'
    }
  }
  /**
   * Before plugin initialized, cannot access to this here
   * @param { { index?: number, player: object, pluginName: string, config: { [propName: string]: any }} args
   */
  beforeCreate(args) {}
  /**
   * After plugin created, we recommand you to add event listeners here
   */
  afterCreate () {
    this.on(Events.PLAY, () => {
      console.log(this.config.text) // 'default text for plugin'
    })
  }
  /**
   * before player starting to load
   */
  beforePlayerInit () {

  }
  /**
   * DOM of media element was created, player.video as accessable
   */
  afterPlayerInit () {

  }
  /**
   * Plugin instance destroyed
   */
  destroy () {

  }
}

Plugin

Plugin extends BasePlugin by adding render hook and DOM APIs

import { Plugin } from 'xgplayer'
import IconSVG from './my-icon'
const { POSITIONS } = Plugin

// myPlugin.js
export default class MyPlugin extends Plugin {
  /**
   * (required) name and identifier of this plugin
   * you can find、configure、deregister plugin by pluginName, for example:
   *
   * const p = new player({
   *   [myPlugin]: {
   *     position: POSITIONS.CONTROLS_LEFT
   *   }
   * })
   **/
  static get pluginName() {
    return 'myPlugin'
  }

  static get defaultConfig () {
    return {
      // Which area for current plugin to mount on
      position: POSITIONS.CONTROLS_RIGTH,
      // Index of plugin,
      index: 0,
    }
  }
  /**
   * Before plugin initialized, cannot access to this here
   * @param { { index: number, player: object, pluginName: string, config: { [propName: string]: any }, root: HTMLElement, position: string}} args
   */
  registerIcons () {
    return {
      myIcon: { icon: IconSVG, class: 'custom-icon' },
    }
  }
  /**
   * Before plugin initialized, cannot access to "this" here cause DOM and APIs not ready
   * @param { { index: number, player: object, pluginName: string, config: { [propName: string]: any }, root: HTMLElement, position: string}} args
   */
  beforeCreate(args) {
  }

  afterCreate () {
    // Bind click event to icon DOM node
    this.bind('.icon', 'click', this.onIconClick)
    // Bind click event to root DOM node
    this.bind('click', this.onClick)

  }
  onClick () {
    console.log('root of plugin was clicked')
  }
  onIconClick () {
    console.log('div.icon was clicked')
  }
  initIcons () {
    const { icons } = this
    this.appendChild('.icon', icons.myIcon)
  }

  destroy () {
    this.unbind('.icon', 'click', this.onIconClick)
    this.unbind('click', this.onClick)
    this.icon = null
  }

  render () {
    return `<div class="my-plugin">这是一个dmeo插件<div class="icon"></div></div>`
  }
}

Use plugin

You can use plugin by pass it to player.config or invoke player.registerPlugin

import Player from 'xgplayer'
import MyBasePlugin from './my-base-plugin.js'
import MyPlugin from '../my-plugin.js'

const player = new Player({
  url: '../video/mp4/xgplayer-demo-720p.mp4',
  plugins: [MyBasePlugin],
})
// register plugin dynamically
player.registerPlugin(MyPlugin)

Reserved config position

Use position config to specify where the plugin should mount on

default layoutimage.png

flex layoutimage.png

  • If position is not specified, plugin will mount on the root node;
  • Position ROOT_TOP、ROOT_RIGHT、ROOT_LEFT would auto hide when player unfocused

Reserved config index

Plugins are sorted by it's index, small index indicates high priority. If there are two plugins with the same index, player would render them by register order

Lifecycle hooks

beforeCreate

Plugin is being inited, cannot access to properties in beforeCreate hook

render

Only in Plugin (not BasePlugin), DOM string or DOM node is needed as return value

afterCreate

Invoked after plugin instance created, you can access to properties in afterCreate hook, for example: this.player or this.el

onPluginsReady

All of the plugins are created, you can access to this.player.plugins[pluginName] for other plugin instances.

destory

Plugin is destroyed by player

beforePlayerInit

Before player start to load media resource

afterPlayerInit

Media resource was loaded by player

Reserved properties

player[readonly]

Player instance, for example you can pause player using this.player.pause()

playerConfig[readonly]

The same with this.player.config

pluginName[readonly]

Name and identifier of current plugin

root[readonly]

Root node of plugin, counld be accessed by this.root in plugin

Built-in API

on (event, callback)

  • Listen to player events

  • Tip: plugin would automatically remove eventlistener during plugin destroy

this.on(Events.PLAY, () => {
  console.log('play')
})
// Listen to multiple events
this.on([Events.ENDED, Events.PAUSE], () => {
  console.log('ended or pause')
})

once (event, callback)

  • Listen to player events and the callback would be triggered only once

  • Tip: plugin would automatically remove eventlistener during plugin destroy

this.once(Events.PLAY, () => {
  console.log('play')
})

off (event, callback)

  • Remove player event listener
this.off(Events.PLAY, () => {
  console.log('play')
})
// Remove multi event listenning
this.off([Events.ENDED, Events.PAUSE], () => {
  console.log('ended or pause')
})

offAll ()

Remove all event listeners

this.offAll()

emit (event)

emit event to player

this.emit('customEvent')

plugins

get plugin instances

const plugin = this.plugins[pluginName]

getPlugin(pluginName)

Another way to access to plugin instance

const pc = this.getPlugin('pc')

[Invalid in BasePlugin]registerPlugin (Plugin, options, name)

  • Register a plugin that mount on current plugin
    • If options.root is specified, new plugin would mount on options.root, or it would be mounted on root node of current plugin
    • You can override identifier of new plugin by pasing name
// Assuming that CustomPlugin has the pluginName of 'customPlugin'
import CustomPlugin from './customplugin'

/**
 * You can get new plugin instance by player.plugins.customPlugin
 * Custom Plugin would be mounted on root node of current plugin
 */
const child1 = this.registerPlugin(CustomPlugin)

/**
 * You can get new plugin instance by player.plugins.csplugin
 */
const child = this.registerPlugin(CustomPlugin, {
  // specified the mount point of CustomPlugin
  root: this.find('.childdiv'),
  // config for CustomPlugin
  config: {
    text: 'custom plugin'
  }, 'csplugin'});

show

Show current plugin

plugin.show()
// show with a specified css display value, default to block
plugin.show('flex')

hide

Hide plugin

find (selector)

find node within the root node, using querySelector

// find the first dom with className "icon"
this.icon = this.find('.icon')

bind (selector, event, handler)

  • add event listeners to DOM node within root node of plugin, note that you need to remove listeners manually by unbind API

this.bind('li a', 'click', this.clickHandler)
this.unbind('li a', 'click', this.clickHandler)

// bind event listener to root node
this.bind('click', this.clickHandler)
this.unbind('click', this.clickHandler)

// for multi events
this.bind('li a', ['click', 'touched'], this.clickHandler)
this.unbind('li a', ['click', 'touched'], this.clickHandler)

unbind (selector, event, handler)

Remove event listeners from bind API

setStyle;

  • @param { string | {[propName: string]: any} } name

  • @param { any? } value

Set style for root node of the plugin

// Set style property
this.setStyle('height', '40px')
// Set multiple style properties
this.setStyle({
  'height': '40px',
  'width': '40px'
})

setAttr (name, value)

Set DOM attributes for root node of the plugin


this.setAttr('data-url', 'https://ixigua.com')
// Set multiple DOM attributes
this.setAttr({
  'data-id': 1,
  'data-name': 'name'
})

setHtml (htmlStr, callback)

Set innerHTML for root node of the plugin


this.setHtml(`<div class="icon">newIcon</div>`)

Enum

Plugin.POSITIONS

Plugin.POSITIONS = {
  ROOT: 'root',                     // mount on root node of the player
  ROOT_LEFT: 'rootLeft',            // mount on left side bar of the player
  ROOT_RIGHT: 'rootRight',          // mount on right side bar of the player
  ROOT_TOP: 'rootTop',              // mount on top bar of the player
  CONTROLS_LEFT: 'controlsLeft',    // mount on control bar's left of the player
  CONTROLS_RIGHT: 'controlsRight',  // mount on control bar's right of the player
  CONTROLS_CENTER: 'controlsCenter' // mount on middle of control bar of the player
}