Revert "feat: enhance Danmuku plugin with batch processing for top calculations"

This reverts commit 1841f754dc.
This commit is contained in:
Harvey Zhao committed 2026-03-05 13:58:53 +08:00
1 parent e112b33f97
commit 3ae89ab349
4 files changed
+65 -251

No files matched your search

@@ -32,21 +32,6 @@ export default class Danmuku {
const blob = new Blob([workerText2], { type: 'application/javascript' })
this.worker = new Worker(URL.createObjectURL(blob))
// Web Worker 回调池,避免频繁覆盖 onmessage 并支持并发请求
this.workerCallbacks = new Map()
this.worker.onmessage = (event) => {
const { data } = event
if (!data || !data.id)
return
const callback = this.workerCallbacks.get(data.id)
if (callback) {
this.workerCallbacks.delete(data.id)
callback(data)
}
}
// 绑定公用事件
this.start = this.start.bind(this)
this.stop = this.stop.bind(this)
@@ -452,10 +437,15 @@ export default class Danmuku {
// 复杂运算交给 Web Worker 处理
postMessage(message = {}) {
return new Promise((resolve) => {
const id = `${Date.now()}-${Math.random()}`
message.id = id // 生成唯一标识
this.workerCallbacks.set(id, resolve)
message.id = Date.now() // 生成唯一标识
this.worker.postMessage(message)
this.worker.onmessage = (event) => {
const { data } = event
// 判断是否是当前的消息
if (data.id === message.id) {
resolve(data)
}
}
})
}
@@ -470,14 +460,8 @@ export default class Danmuku {
// 设置弹幕状态
setState(danmu, state) {
// 从原状态池中删除,使用原地删除避免创建新数组
const prevState = danmu.$state
if (prevState && this.states[prevState]) {
const list = this.states[prevState]
const index = list.indexOf(danmu)
if (index !== -1)
list.splice(index, 1)
}
// 从原状态池中删除
this.states[danmu.$state] = this.states[danmu.$state].filter(item => item !== danmu)
// 设置新状态
danmu.$state = state
@@ -511,65 +495,28 @@ export default class Danmuku {
this.timer = window.requestAnimationFrame(async () => {
if (this.art.playing && !this.isHide) {
const now = Date.now()
const { clientWidth, clientHeight } = this.$player
// 实时计算弹幕的剩余显示时间,并构建当前可见弹幕数据,避免重复 DOM 读写
const visibles = []
const playerLeft = this.getLeft(this.$player)
// 实时计算弹幕的剩余显示时间
this.filter('emit', (danmu) => {
const emitTime = (now - danmu.$lastStartTime) / 1000
const emitTime = (Date.now() - danmu.$lastStartTime) / 1000
danmu.$restTime -= emitTime
danmu.$lastStartTime = now
danmu.$lastStartTime = Date.now()
// 超过时间即重置弹幕
if (danmu.$restTime <= 0) {
this.makeWait(danmu)
return
}
if (!danmu.$ref)
return
const top = danmu.$ref.offsetTop
const left = this.getLeft(danmu.$ref) - playerLeft
const height = danmu.$ref.clientHeight
const width = danmu.$ref.clientWidth
const distance = left + width
const right = clientWidth - distance
const speed = distance / danmu.$restTime
visibles.push({
top,
left,
height,
width,
right,
speed,
distance,
time: danmu.$restTime,
mode: danmu.mode,
})
})
// 获取准备好发送的弹幕,可能包含ready和wait状态的弹幕
const readys = this.readys
if (readys.length) {
const topsTargets = []
const readyDanmus = []
for (let index = 0; index < readys.length; index++) {
const danmu = readys[index]
// 先初始化 DOM、样式及 target 数据,统一批量计算 top
for (let index = 0; index < readys.length; index++) {
const danmu = readys[index]
// 弹幕发送前的过滤器(保持顺序执行,避免行为变化)
// eslint-disable-next-line no-await-in-loop
const state = await this.option.beforeVisible(danmu)
if (!state)
continue
// 弹幕发送前的过滤器
const state = await this.option.beforeVisible(danmu)
if (state) {
const { clientWidth, clientHeight } = this.$player
danmu.$ref = this.$ref // 获取弹幕DOM节点
danmu.$ref.textContent = danmu.text // 设置弹幕文本
@@ -587,29 +534,23 @@ export default class Danmuku {
setStyles(danmu.$ref, danmu.style)
// 记录弹幕时间戳
danmu.$lastStartTime = now
danmu.$lastStartTime = Date.now()
// 计算弹幕剩余时间
danmu.$restTime = this.speed
const height = danmu.$ref.clientHeight
// 计算弹幕滚动的距离
const distance = clientWidth + danmu.$ref.clientWidth
const speed = distance / danmu.$restTime
topsTargets.push({
mode: danmu.mode,
height,
speed,
})
readyDanmus.push({ danmu, distance })
}
if (topsTargets.length) {
const { result: tops } = await this.postMessage({
type: 'getDanmuTopBatch',
targets: topsTargets,
visibles,
// 计算弹幕的top值
const { result: top } = await this.postMessage({
type: 'getDanmuTop',
target: {
mode: danmu.mode,
height: danmu.$ref.clientHeight,
speed: distance / danmu.$restTime,
}, // 当前弹幕信息
visibles: this.visibles, // 可见的弹幕的数据
antiOverlap: this.option.antiOverlap,
clientWidth,
clientHeight,
@@ -617,13 +558,7 @@ export default class Danmuku {
marginTop: this.marginTop,
})
for (let index = 0; index < readyDanmus.length; index++) {
const { danmu, distance } = readyDanmus[index]
const top = Array.isArray(tops) ? tops[index] : undefined
if (!danmu.$ref)
continue
if (danmu.$ref) {
if (!this.isStop && top !== undefined) {
this.setState(danmu, 'emit') // 转换为emit状态
danmu.$ref.style.top = `${top}px`
@@ -786,9 +721,6 @@ export default class Danmuku {
destroy() {
this.stop()
if (this.workerCallbacks) {
this.workerCallbacks.clear()
}
this.worker.terminate()
this.art.off('video:play', this.start)
this.art.off('video:playing', this.start)
@@ -135,29 +135,12 @@ function getDanmuTop({ target, visibles, clientWidth, clientHeight, marginBottom
}
}
function getDanmuTopBatch({ targets, visibles, clientWidth, clientHeight, marginBottom, marginTop, antiOverlap }) {
if (!Array.isArray(targets) || targets.length === 0)
return []
return targets.map((target) => {
return getDanmuTop({
target,
visibles,
clientWidth,
clientHeight,
marginBottom,
marginTop,
antiOverlap,
})
})
}
onmessage = (event) => {
const { data } = event
if (!data.id || !data.type)
return
const fns = { getDanmuTop, getDanmuTopBatch }
const fns = { getDanmuTop }
const fn = fns[data.type]
const result = fn(data)