List对象的方法调用暂不支持链式语法。
- Demo
- 创建列表
new()
- 删除列表
del()
- 切换到某个列表
use()
- 向当前列表中添加弹幕
addDm()
- 从当前列表中移除弹幕
delDm()
- 根据时刻从当前列表中创建弹幕
tick()
- 调整当前列表的时刻不确定度
uncertainty()
- 往当前列表中载入一批弹幕
load()
- 导出当前列表
export()
danmaku.list.new(listName)
listName
- 待创建的列表名称
要使用列表,需要先创建列表,不是嘛!
danmaku.list.del(listName)
listName
- 待删除的列表名称
列表不要了就用这个方法删了罢
danmaku.list.use(listName)
listName
- 待切换的列表名称
接下来的方法都必须要先通过此方法“切换到”列表中才能使用。
借用一下数据库管理系统的use
danmaku.list.addDm(dmData, time)
-
dmData
- 待添加的弹幕数据 -
time
- 弹幕出现的时刻,单位为毫秒(ms) -
返回值:弹幕在列表中的代号
danmakuSerial
使用前提:使用
use()
方法切换到了列表中
取值为一个对象,包含一条弹幕的数据。
示例对象:
{
text: '', // 弹幕内容
reset_styles: false, // 是否在设置样式前重置样式,否则继承之前的样式
styles: {...}, // 弹幕样式
created: null // 同danmaku.create的创建后回调created()
callback: null // 同danmaku.create的弹幕结束后回调callback()
}
取值为一个整数,单位为毫秒(ms),代表弹幕出现的时刻。
比如在955ms
处插入一条蓝色弹幕,并在创建该弹幕时重置样式:
danmaku.list.addDm({
text: '这是一条逆向滚动弹幕',
reset_styles: true,
styles: {
color: 'blue'
}
}, 955);
danmaku.list.delDm(danmakuSerial)
-
danmakuSerial
- 待从当前列表中移除的弹幕代号 -
返回值:布尔值
true
/false
,代表是/否移除成功
使用前提:使用
use()
方法切换到了列表中
取值为一个字符串,代表当前列表中某条弹幕的代号。
弹幕代号在用addDm()
方法添加弹幕时会返回。
danmaku.list.tick(time)
time
- 需要检查的时刻,单位为毫秒(ms)
使用前提:使用
use()
方法切换到了列表中
光在列表中添加了弹幕,该怎么让这些弹幕被创建出来捏?这就不得不提到咱们的tick()
方法了!
通过调用该方法,程序会在列表中寻找在time
时刻(或附近)的弹幕,并创建命中的弹幕。
为什么还加了一小句“或附近”呢?看接下来这一个方法吧!
danmaku.list.uncertainty(time)
-
time
- 不确定时间段,单位为毫秒(ms) -
每一个列表的默认时刻不确定度为
200ms
使用前提:使用
use()
方法切换到了列表中
上面的tick()
方法会搜索某一时刻的弹幕并加以创建。
实际使用中,媒体的时间精确度可能达不到毫秒级,但弹幕时刻精确到了毫秒,这就导致如果tick(媒体时刻)
的话,可能有些弹幕不会被创建出来。
因此引入了时刻不确定度。
danmaku.list.uncertainty(0);
danmaku.list.tick(200);
这个时候仅搜索在时刻200ms
处的弹幕,图中的弹幕2会被创建:
danmaku.list.uncertainty(45);
danmaku.list.tick(200);
这个时候搜索的是一段时间范围内( 200 ± 45 ms
)的弹幕,图中的弹幕2、弹幕3会被创建:
骚年,你是否在顾虑这种情况?
我超,两次tick
过近了,但uncertainty
指定的弹幕搜索范围比较大,两次的搜索范围发送了重叠!这怎么整?
哈哈,实际上咱考虑到了这点,发生重叠情况的时候会自动调整搜索范围,所以不用担心的啦~
在网页媒体中使用弹幕列表时,你可能会用到timeupdate
事件:
video.addEventListener('timeupdate', function(e) {
let currentMilli = Math.round(e.target.currentTime * 1000);
danmaku.list.tick(currentMilli);
});
按照MDN文档的说明,基本上能保证该事件每秒被触发4-66
次,大概每两次事件触发之间是15ms-250ms
的时间间隔。
因此咱建议在这里设置时刻不确定度为300ms-500ms
,这样能最大程度上保证弹幕的创建。
如果timeupdate
实在不确定性太大了,你其实可以使用setInterval()
来定时tick()
,只不过需要手动处理暂停/播放相关的事件。
danmaku.list.load(danmakuArr)
-
danmakuArr
- 待载入的包含弹幕数据的数组 -
返回值:布尔值
true
/false
,代表是/否载入成功
使用前提:使用
use()
方法切换到了列表中
当弹幕数量很大时,使用addDm()
方法一条一条地添加弹幕到列表中实在是太麻烦了,因此有了这个load()
方法,将一批弹幕一次性添加到列表中。
取值为一个数组,这个数组的每一个元素是一个弹幕数据对象。
弹幕数据对象示例如下:
{
time: 0, // 弹幕出现的时刻,单位为毫秒(ms)
text: '', // 弹幕内容
reset_styles: false, // 是否在设置样式前重置样式,否则继承之前的样式
styles: {...}, // 弹幕样式
created: null // 同danmaku.create的创建后回调created()
callback: null // 同danmaku.create的弹幕结束后回调callback()
}
danmakuArr
数组示例:
[
{
time: 1098,
text: '这是一条无描边,底部悬停的绿色弹幕',
styles: {
color: 'green',
life: 4000,
outline: false,
type: 'bottom',
'bottom_space': 30
}
},
{
time: 1072,
text: '这是一条随机黄色弹幕',
styles: {
color: 'yellow',
life: 4000,
outline: false,
type: 'random',
'bottom_space': 2
}
}
]
创建一个JavaScript文件作为弹幕数据文件,可以这样写:
const myList = [ // 这里咱就放两条测试弹幕
{
time: 2000,
text: '测试弹幕1'
},
{
time: 1002,
text: '测试弹幕2'
}
]
将这个文件命名为myList.js
。
在页面中载入这个文件中的弹幕数据,可以这样写:
<div id="danmaku-container"><!--弹幕容器--></div>
<script src="./myList.js"></script> <!--此时myList变量暴露到全局-->
<script src="./N.min.js"></script>
<script>
const danmaku = new NDanmaku('danmaku-container');
danmaku.list.new('test'); // 新建列表test
danmaku.list.use('test'); // 切换到列表test
danmaku.list.load(myList); // 载入myList到列表test中
</script>
创建一个JSON文件作为弹幕数据文件,可以这样写:
[ // 这里咱就放两条测试弹幕
{
"time": 2000,
"text": "测试弹幕1"
},
{
"time": 1002,
"text": "测试弹幕2"
}
]
将这个文件命名为myList.json
。
在页面中载入这个文件中的弹幕数据,可以这样写:
<div id="danmaku-container"><!--弹幕容器--></div>
<script src="./myList.js"></script> <!--此时myList变量暴露到全局-->
<script src="./N.min.js"></script>
<script>
const danmaku = new NDanmaku('danmaku-container');
danmaku.list.new('test'); // 新建列表test
danmaku.list.use('test'); // 切换到列表test
fetch('./myList.json')
.then(res => res.json())
.then(data => danmaku.list.load(data)); // 载入myList到列表test中
</script>
danmaku.list.export(outputName, fileType = 'js', download = false)
-
outputName
- 输出的列表名,同时也是不包括扩展名的文件名 -
fileType
- 输出的文件类型,可选值为js
或json
,默认为js
-
download
- 是否触发浏览器文件下载,默认为false
-
返回值:文件内容字符串,如果失败了则为空字符串
''
使用前提:使用
use()
方法切换到了列表中
这个方法可以说和load()
是反着来的,它可以将当前列表导出为字符串/文件。
取值为一串字符串,代表输出的列表名。
值得注意的是,传入这个参数时有一定限制:传入的字符串必须满足JavaScript的变量命名规则。
简单说来,就是:字符串每个字符只能是字母、数字、美元符号
$
、下划线_
,且首个字符不能是数字。
-
默认值:
'js'
-
可选值:
'js'
或'json'
取值为一串字符串,代表导出的文件类型。根据文件类型不同,最终程序生成的文件内容也不同。
对于.js
文件来说,导出的时候支持导出列表中弹幕的回调函数;但是对于.json
文件来说是肯定不支持这点的。
- 默认值:
false
(默认不触发下载)
取值为一个布尔值true
/false
。
如果为true
,程序会将文件内容写入文件,并触发浏览器下载。文件名为 outputName
+ 后缀。
const testDm = [
{
"text": "这是一条蓝色弹幕",
"styles": {
"life": 7000,
"color": "blue",
"reverse": false,
"bottom_space": 2,
"type": "scroll",
},
// 如果导出.js文件,是支持导出回调函数的!
"created": (element, id) => {
element.onmouseover = () => {
dmCon.pause(id);
}
element.onmouseout = () => {
dmCon.resume(id);
}
},
"time": 1001,
},
{
"text": "测试弹幕2",
"time": 2002,
},
]