Skip to content

Commit

Permalink
Merge pull request #1 from August-Z/raf
Browse files Browse the repository at this point in the history
v1.3.2 RAF
  • Loading branch information
August-Z authored Mar 23, 2019
2 parents 57b83f4 + b40beb8 commit 93ed4f2
Show file tree
Hide file tree
Showing 11 changed files with 193 additions and 104 deletions.
170 changes: 127 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,68 +12,152 @@ awesome-danmaku 是一款解决前端弹幕场景需求的插件。它基于原
$ npm install awesome-danmaku
```


## 使用

最简易的起步

```html
<div id="app"></div>
```
```js
// use CommonJS
const DanmakuControl = require('awesome-danmaku').control

const danmakuPlayer = DanmakuControl.getPlayer('#app')


// use ES module
import Danmaku from 'awesome-danmaku'
const player = Danmaku.control.getPlayer('#app')

const danmakuPlayer = Danmaku.control.getPlayer('#app')
// play 和 insert 这两个主要操作没有先后次序的要求,你亦可以先插入后再启动控制器
danmakuPlayer.play()
danmakuPlayer.insert([
'Hello Awesome Danmaku!',
'我是第1条弹幕...',
'我是第2条弹幕...',
'我是第3条弹幕...',
])
```

## API

// 调用 play 即可开始不断发送弹幕,insert 可以插入弹幕
// 这两个主要动作没有先后次序的要求,你亦可以先插入后再启动控制器
danmakuPlayer.play()
.insert('Hello')
.insert('Awesome Danmaku !')

danmakuPlayer.insert({
value: 'I feel good.'
### Control(selectors | HTMLElement | config): Player
```js
// 获取弹幕机 Player
Control.getPlayer('#app')

// 传入更详细的配置,这里增加了「弹幕最大数」与「弹幕轨道数」的参数
Control.getPlayer({
el: '#app',
maxCount: 50,
trackCount: 5
})
```

// 暂停运行
danmakuPlayer.pause()

// 清空当前已插入的弹幕列表
danmakuPlayer.clearList()

### Player
##### play()
```js
// 启动弹幕机
Player.play()
```

使用一些配置项
##### pause()
```js
// 暂停弹幕机,重启可直接使用 play()
Player.pause()
```

##### stop()
```js
const danmakuPlayer = DanmakuControl.getPlayer({
el: '#demo-b',
rollingTime: 3000,
nodeTag: 'div',
nodeClass: 'demo-b-item',
nodeMaxCount: 10,
nodeValueKey: 'text',
trackList: 7,
trackHeight: 70,
on: {
play () {
console.log('Demo-b Start playing !!')
}
}
})
// 关闭弹幕机,清空弹幕发送队列与数据
Player.stop()
```

danmakuPlayer.insert({
text: 'used some config'
##### insert(string | config [, sync])
```js
// 将弹幕内容置入弹幕机
// sync 默认为 false,该条弹幕会进入弹幕发送队列
Player.insert('Hello Awesome-Danmaku!')

// sync 为 true 时,该条弹幕将立即显示(插队)
Player.insert({
value: 'Hello Awesome-Danmaku!',
opacity: 0.8,
color: '#ff0000',
})

// 参数可以以数组方式传递
Player.insert([
'这是一条普通的弹幕',
{
value: '这是一条有点黄的弹幕',
color: '#ffff00'
}
])
//
```


## 配置

TODO 编写中...
##### 弹幕机 - Player Config
```js
// 下方值除 el 外均为该属性的默认值
const PlayerConfig = {

// 弹幕机创建所需要的 DOM 节点,可以传递字符串选择器或者是具体的 DOM 对象
el: '#app',

// 每条弹幕运动的总时长,单位为毫秒
rollingTime: 6000,

// 弹幕节点的 DOM 标签,大小写不敏感
nodeTag: 'p',

// 弹幕节点的类名,可通过这里修改弹幕的样式
nodeClass: 'awesome-danmaku-item',

// 弹幕节点的最大值,该值设置过大可能会影响运行性能
nodeMaxCount: 25,

// 传入弹幕机的节点文本key,通常不设为空,为空时默认为'text'
nodeValueKey: 'value',

// 弹幕机轨道数
trackCount: 5,

// 弹幕机轨道高度,单位为 px
trackHeight: 40,

// 弹幕机的节点列表,可传入弹幕节点
list: []
}
```
##### 弹幕节点 - Node Config
```js
const nodeConfig = {
// 弹幕文本,该枚举 key 可根据弹幕机 nodeValueKey 调整
text: '',

// 弹幕字体大小,为数字时单位为px,其他单位可通过字符串传递
fontSize: 22,

// 弹幕字体
fontFamily: 'SimHei',

// 弹幕字重
fontWeight: 'normal',

// 不透明度
opacity: 1,

// 弹幕字体颜色
color: '#FFFFFF',

// 弹幕速度系数,取值范围(>0),标准为1
speed: 1
}
```

## 版本更新

### v1.3.1
player#insert(string | config [, sync])
现在使用 insert() 插入弹幕时,可添加第二个参数,将发送弹幕立即显示

### v1.3.0
使用 window.requestAnimationFrame 代替了原有的队列定时器逻辑

4 changes: 2 additions & 2 deletions dist/danmaku.browser.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/danmaku.common.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/danmaku.esm.js

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion flow/track.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
declare type DtrackOptions = {
index: number;
height: number;
overlap: number;
}
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
</head>
<body>
<div id="demo-a"></div>
<div id="demo-b"></div>
<!--<div id="demo-b"></div>-->
<div class="slider-box">
<div class="slider-item density">
<div class="slider-label">弹幕密度</div>
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "awesome-danmaku",
"version": "1.1.8",
"version": "1.3.2",
"description": "Danmaku components for HTML5",
"main": "dist/danmaku.common.js",
"module": "dist/danmaku.esm.js",
Expand Down
83 changes: 52 additions & 31 deletions src/core/control/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { DanmakuControlEvent } from "../event";
export class DanmakuPlayer {

_loopTime: number
_overlap: number

el: HTMLElement
rollingTime: number
Expand Down Expand Up @@ -70,36 +71,61 @@ export class DanmakuPlayer {

/**
* 向弹幕播放器中添加弹幕
* @param danmaku<Array<DnodeOptions> | DnodeOptions | string>
* @param danmakuOps
* @param sync
*/
insert (danmaku: any): Array<DnodeOptions> {
this.list.push(
...this._handleDanmakuOps(danmaku)
)
insert (danmakuOps: any, sync?: boolean = false): Array<DnodeOptions> {
if (sync) {
// 同步模式,发送的文本会实时显示 (这里不经过发送队列,直接创建一个临时的 Dnode)
const nodeTag: string = this.nodeTag.toLowerCase()
const nodeDom: HTMLElement = document.createElement(nodeTag)
const nodeOps: DnodeOptions = this._handleDanmakuOps(danmakuOps).shift()
const node: Dnode = new Dnode({
control: self,
...__CONFIG__.DnodeDefaultConfig.getDefault,
...nodeOps
}).init(nodeDom)
nodeDom.setAttribute('class', this.nodeClass)
this.el.appendChild(nodeDom)
node.patch(nodeOps).run((n: Dnode) => {
this.el.removeChild(nodeDom)
})
} else {
// 常规的异步模式,弹幕的发送会经过发送队列
this.list.push(
...this._handleDanmakuOps(danmakuOps)
)
}
return this.list
}


play (): DanmakuPlayer {

if (!Array.isArray(this.list)) {
throw new TypeError('list must instanceof Array')
}
else if (['static', 'static !important', ''].includes(getComputedStyle(this.el).position)) {
} else if (['static', 'static !important', ''].includes(getComputedStyle(this.el).position)) {
throw new Error(
'Play error! el (wrap dom) position can\'t is static or empty, \n' +
'Please set \"relative\"、\"absolute\" or \"fixed\".'
)
}

// eval
clearInterval(this.playTimer)
this.playTimer = setInterval(() => {
this.playTick()
}, this._loopTime)
let self = this
let counter = 0

function tickTask () {
requestAnimationFrame(tickTask)
if (++counter % self._overlap === 0) {
counter = 0
self.playTick()
}
}

requestAnimationFrame(tickTask)

this.playStatus = DanmakuControlPlayStatus.PLAY
this._controlHook(DanmakuControlEventName.PLAY)

return this
}

Expand Down Expand Up @@ -158,21 +184,12 @@ export class DanmakuPlayer {
case 'speed' :
this._changeSpeed(Number(val))
break
default:
console.warn(
`[Change WARN]: The player not has \'${key}\' param! Or this property is readonly.\n`
)
}
}

changeTrack (key: string, val: any) {
switch (key) {
case 'overlap':
this._changeTrackOverlap(Number(val))
this._changeOverlap(Number(val))
break
default:
console.warn(
`[Change WARN]: The track not has \'${key}\' param! Or this property is readonly.\n`
`[Change WARN]: The player not has \'${ key }\' param! Or this property is readonly.\n`
)
}
}
Expand Down Expand Up @@ -227,6 +244,7 @@ export class DanmakuPlayer {

_initSelfConfig (): DanmakuPlayer {
this._loopTime = Number(Math.round(this.rollingTime / this.nodeMaxCount) + __CONFIG__.TICK_TIME)
this._overlap = 15
return this
}

Expand Down Expand Up @@ -260,8 +278,7 @@ export class DanmakuPlayer {
this.trackList.push(new Dtrack({
index: i,
width: this.playerWidth,
height: this.trackHeight,
overlap: 1
height: this.trackHeight
}))
}
return this
Expand All @@ -272,7 +289,7 @@ export class DanmakuPlayer {
const nodeTag: string = this.nodeTag.toLowerCase()
for (let i = 0; i < this.nodeMaxCount; i++) {
// language=HTML
nodeListHTML += `<${nodeTag} class="${this.nodeClass}"></${nodeTag}>`
nodeListHTML += `<${ nodeTag } class="${ this.nodeClass }"></${ nodeTag }>`
}
this.el.innerHTML = nodeListHTML
setTimeout(() => {
Expand Down Expand Up @@ -374,10 +391,14 @@ export class DanmakuPlayer {
})
}

_changeTrackOverlap (val: number): void {
this.trackList.forEach((t: Dtrack) => {
t.setOverlap(val)
})
/**
* 映射到 overlap 值 (1~20)
* @param val 0.00 - 1.00
* @private
*/
_changeOverlap (val: number): void {
let v = Math.round((1 - val) * 20) + 5
this._overlap = Math.min(25, Math.max(5, v))
}

_controlHook (hookName: string): void {
Expand Down
2 changes: 1 addition & 1 deletion src/core/node/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export class Dnode {
setTimeout(() => {
t.stopRolling()
this.runStatus = DnodeRunStatus.LAUNCHED
}, this.launchTime * this.track.overlap)
}, this.launchTime)

// 弹幕经过了总运动时长,此时已到达轨道终点,此处 Status => RunEnd
setTimeout(() => {
Expand Down
Loading

0 comments on commit 93ed4f2

Please sign in to comment.