# 组件

# 控制条

NiPlayer播放器中控制条从上至下分为三类: 分别为TopBar,MediumBar,BottomBar,用户可以随意更改控制条内的组件,比如某些组件的挂载和卸载,也可以注册自己的组件.因此就算播放器的默认样式用户不满意,完全可以自己定制样式

# 例:更改最底部控制条的组件:

例如用户觉得底部右侧的组件过于冗余,只想保存其中的全屏和设置组件,那么可以这么做:

import Player from "niplayer"
import { FullScreen,FullPage,SubSetting } from "niplayer" // 引入播放器的内置组件
let player = new Player({
    url: "https://novaex.cc/OnePiece.mp4",
    container:document.getElementById("video"),
    rightBottomBarControllers: [SubSetting,FullPage,FullScreen] // rightBottomBarControllers --> 用于控制右下侧的控制条
})

player.attachSource("https://novaex.cc/OnePiece.mp4")

TIP

其余的部分同理

# 原子组件

TIP

原子组件指的是内部不在包含其他组件,是播放器中组件的最小单位,也是最容易进行更换和定制的组件;NiPlayer中一共内置9种内置组件:

组件名 说明
FullScreen 全屏组件
PageScreen 页面全屏
PicInPic 画中画
ScreenShot 截图
VideoShot 视频录制
SubSetting 设置
Volume 音量
Playbutton 播放按钮
Toast 弹窗组件
import { FullScreen,FullPage,SubSetting,PlayButton,PicInPic,Volume,ScreenShot,VideoShot, } from "niplayer"
// 默认所有内置组件都会挂载到视图上

# 内置组件实例的获取(包括原子组件)

// 所有实例化的组件都会保存在其中,包括用户自定义的组件
import {ONCE_COMPONENT_STORE} from "niplayer"
// 传入组件的id,通常内置组件的id就是其构造函数的名字
let instance = ONCE_COMPONENT_STORE.get("PicInPic")

console.log(instance)

# 自定义组件

TIP

除了内置组件外,用户还可以自定义组件然后挂载到相关的控制条上;

组件的签名项和其继承的基类如下:

// 组件构造函数需要实现的接口
interface ComponentItem {
  id: string; // 组件的标识符
  el: HTMLElement; // 组件对应的DOM元素
  container?: HTMLElement; // 容器 ,可选
  props?: DOMProps; // 组件的属性,包括(className,id,style),最终会挂载到DOM元素上
}
// 组件构造函数需要继承的基类
class Component {
  el: HTMLElement; //el代表着该组件对应的整个HTML元素
  container: HTMLElement; // 组件的容器
  init() {} // 初始化函数
  initEvent() {} //初始化事件
  initPCEvent() {} //初始化PC端事件
  initMobileEvent() {} // 初始化移动端事件
  initTemplate() {} //初始化总的模板(也就是该组件的HTML结构)
  initPCTemplate() {} //初始化PC端模板
  initMobileTemplate() {} //初始化移动端模板
  initComponent() {} //初始化内部的其他组件
  resetEvent() {} //重置事件
  dispose() {} //销毁组件
  constructor(){....}
}

因此如果在JS中需要自定义组件的话

// 此处为JS写法
class MyComponent extends Component{
    constructor(player,container) {
        // player为构造器实例,container为容器
        // 此处的第二个参数代表着组件的标签名,第三个参数中可以写我们的样式
        super(container,"div",{
            id: "MyComponentID",
            className: "MyComponentClassName",
            style:{
                color: "red";
                fontSize: "14px"
            }
        })
        this.id = "MyComponent" //组件必须要存在id!!!
        this.init()
    }

    // 覆写Component中的init函数,也可以不覆写保持其默认行为
    init() {
        this.initEvent();
    }

    initEvent() {
        // 此处可以写我们自己的事件
        console.log(player);
        this.el.onclick = () => {
            alert("click")
        }
    }
}

使用TypeScript你会获得更好的体验:

export class MyComponent extends Component implements ComponentItem {
    readonly id = "MyComponent";
    player: Player;
    constructor(player:Player,container:HTMLElement) {
        super(container);
        this.player = player;
        this.init();
    }

    init() {
        this.initTemplate()
        this.initEvent()
    }

    initTemplate() {
        // 初始化你的dom节点
    }

    initEvent() {
        // 初始化事件
    }
}

最后在定义完成组件构造函数之后便可以挂载上去了:

let player = new Player({
    url: "https://novaex.cc/OnePiece.mp4",
    container:document.getElementById("video"),
    rightBottomBarControllers: [MyComponent]
})

TIP

特别的,除了通过继承Component来实现自己的组件(这只是编写一个最基本组件的方法);如果用户想要实现一个类似于最底层的原子组件的模板并且具有类似的通用行为的话,例如内置全屏组件,鼠标移入会在上面显示tips,并且点击触发事件。那么你可以这么code你的自定义组件

依然JS写法,TS同理

class YourComponent extends Options {
    constructor(
    player, //播放器实例
    container, // 组件容器
    desc, //组件DOM节点的标签名
    props, //DOM节点的属性,包括style,id,class
  ) {
    super(player, container, width, height); //width,height为隐藏部分的宽高,也就是你鼠标移入是显示的部分
    this.init();
  } {}

    // 写入自己想要的组件icon
  init() {
    this.icon = document.createElement("svg");
    this.iconBox.appendChild(this.icon);

    // 隐藏部分div的内容
    this.hideBox.innerHTML = "<h1>隐藏内容</h1>"
  }
}

# 更新组件

用户可以改变内置组件或者自己已经挂载上去的自定义组件。

# 1. 改变组件的ICON图标

对于那些继承Options的内置组件或者自定义组件,提供了方便的替换ICON图标的接口;

import {ONCE_COMPONENT_STORE} from "niplayer"
let instance = ONCE_COMPONENT_STORE(yourname);
instance.replaceIcon(svg) // 替换图标

# 2. 修改组件的样式

import player from "niplayer"
// 1.改变样式
player.updateComponent(id,{
    props: {
        style: {
            color: "red";
            borderRadius: "5px"
        },
        id: "新增ID",
        className: ["1","2"]
        
    },
})
// 2.替换整个dom节点
player.updateComponent(id,{
    el: document.createElement("id"),
    options: {
        // 两种替换方式
        replaceElType: "replaceOuterHTMLOfComponent" | "replaceInnerHTMLOfComponent";
    }
})