NPlayer播放器挂载弹幕
官网地址: nplayer.js.org/docs/
NPlayer 是由 Typescript 加 Sass 编写,无任何第三方运行时依赖,兼容 IE11,支持移动端、支持 SSR、支持直播。高度可定制,所有图标、主题色等都可以替换,并且提供了内置组件方便二次开发。你可以自定义任意多个断点,不仅仅是兼容移动端,只要愿意,你可以非常轻松的兼容手机竖屏、手机横屏、平板等设备。它还拥有插件系统,弹幕功能就是使用插件形式提供,使用时按需引入即可。该播放器还可以接入任何流媒体,如 hls、dash 和 flv 等。
NPlayer安装和使用
通过 npm 、yarn或pnpm 安装
npm i -S nplayer
使用
import Player from 'nplayer'
// 播放器配置
const options = reactive({
······
})
const player = new Player(options)
// #app 页面中容纳视频的元素的 id
player.mount('#app')
其余配置项请前往官网查看。
实现挂载弹幕
安装弹幕插件
npm i -S @nplayer/danmaku
快速上手
- danmakuOptions:nplayer.js.org/docs/ecosys… (弹幕相关的配置)
- items是弹幕对象,参数如下:
interface BulletOption {
color?: string; // 弹幕颜色
text: string; // 弹幕文字
time: number; // 弹幕出现时间(s)
type?: 'top' | 'bottom' | 'scroll'; // 弹幕类型,默认为滚动类型
isMe?: boolean; // 是否是当前用户发送的
force?: boolean; // 是否强制展示该弹幕(弹幕较多,并且是防碰撞模式时,可能会丢弃一部分弹幕)
}
import Player from 'nplayer'
import Danmaku from '@nplayer/danmaku'
const danmakuOptions = {
autoInsert: true,
items: [
{ time: 1, text: '弹幕~' }
]
}
const options = reactive({
······,
plugins: [new Danmaku(danmakuOptions)]
})
const player = new Player(options)
player.mount("#app")
注意事项,见官网文档:
弹幕数组items必须按时间 time 从小到大排序
解析 xml 弹幕
- 浏览器内置的
DOMParser来解析 XML 数据 - 排序用的 sort 方法,数据量过大时可自行优化排序方式
// 是否开启彩色弹幕
const colorfulBarrage = ref(true)
// 挂载弹幕
const mountBarrage = () => {
// 选取本地文件
const fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.accept = '.xml';
fileInput.addEventListener('change', (event) => {
const file = (event.target as HTMLInputElement).files![0];
const reader = new FileReader();
reader.onload = (e) => {
const xmlData = e.target!.result as string;
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlData, "application/xml");
const danmakuElements = xmlDoc.querySelectorAll('d');
const danmuArr: any = [];
danmakuElements.forEach((danmakuElement) => {
const attributes = danmakuElement.getAttribute('p')!.split(',');
const timeInSeconds = parseFloat(attributes[0]);
const danmakuText = danmakuElement.textContent;
// 直接使用展开语法来创建对象,更简洁高效
danmuArr.push({
time: Math.round(timeInSeconds * 1),
text: danmakuText,
color: colorfulBarrage.value ? "#" + attributes[6] : "#FFFFFF",
type: attributes[1] == '1' ? 'scroll' : attributes[1] == '5' ? 'bottom' : 'top',
});
});
// 使用requestAnimationFrame替代setTimeout,优化渲染时机
requestAnimationFrame(() => {
// danmuArr 按时间排序
danmuArr.sort((a, b) => a.time - b.time);
danmakuSource.value = danmuArr;
if (player) {
player.danmaku.resetItems(danmuArr);
} else {
danmakuOptions.items = danmuArr;
}
});
}
reader.readAsText(file);
});
fileInput.click();
}