mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-29 02:51:20 -08:00
refactor(danmuku): [PKG-DANMUKU-06] migrate runtime and preserve public types
This commit is contained in:
1 parent
abc8008da7
commit
24b883d862
64 files changed
+14020
-633
No files matched your search
@@ -0,0 +1,210 @@
|
||||
import type Danmuku from './danmuku'
|
||||
import type { FrameOperation } from './scheduler'
|
||||
import type { DanmuItem } from './types'
|
||||
|
||||
export default class Renderer {
|
||||
declare owner: Danmuku
|
||||
declare nodes: Set<HTMLDivElement>
|
||||
|
||||
constructor(owner: Danmuku) {
|
||||
this.owner = owner
|
||||
this.nodes = new Set()
|
||||
}
|
||||
|
||||
acquire() {
|
||||
const $ref = this.owner.$refs.pop() || document.createElement('div')
|
||||
$ref.style.cssText = this.owner.constructor.cssText
|
||||
$ref.dataset.mode = ''
|
||||
$ref.dataset.id = ''
|
||||
$ref.className = ''
|
||||
this.nodes.add($ref)
|
||||
return $ref
|
||||
}
|
||||
|
||||
get visibles(): { top: number, left: number, height: number, width: number, right: number, speed: number, distance: number, time: number, mode: number }[] {
|
||||
const result: Renderer['visibles'] = []
|
||||
const { clientWidth } = this.owner.$player
|
||||
const clientLeft = this.owner.getLeft(this.owner.$player)
|
||||
|
||||
this.owner.filter('emit', (danmu) => {
|
||||
const top = danmu.$ref!.offsetTop
|
||||
const left = this.owner.getLeft(danmu.$ref!) - clientLeft
|
||||
const height = danmu.$ref!.clientHeight
|
||||
const width = danmu.$ref!.clientWidth
|
||||
const distance = left + width
|
||||
const right = clientWidth - distance
|
||||
const speed = distance / danmu.$restTime
|
||||
|
||||
const emit = {} as Renderer['visibles'][number]
|
||||
emit.top = top
|
||||
emit.left = left
|
||||
emit.height = height
|
||||
emit.width = width
|
||||
emit.right = right
|
||||
emit.speed = speed
|
||||
emit.distance = distance
|
||||
emit.time = danmu.$restTime
|
||||
emit.mode = danmu.mode
|
||||
|
||||
result.push(emit)
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
left($ref: HTMLElement): number {
|
||||
const rect = $ref.getBoundingClientRect()
|
||||
return this.owner.isRotate ? rect.top : rect.left
|
||||
}
|
||||
|
||||
makeWait(danmu: DanmuItem) {
|
||||
this.owner.setState(danmu, 'wait')
|
||||
if (danmu.$ref) {
|
||||
danmu.$ref!.style.cssText = this.owner.constructor.cssText
|
||||
danmu.$ref!.style.visibility = 'hidden'
|
||||
danmu.$ref!.style.marginLeft = '0px'
|
||||
danmu.$ref!.style.transform = 'translateX(0px)'
|
||||
danmu.$ref!.style.transition = 'transform 0s linear 0s'
|
||||
this.owner.$refs.push(danmu.$ref)
|
||||
danmu!.$ref = null
|
||||
}
|
||||
}
|
||||
|
||||
resize() {
|
||||
const { clientWidth } = this.owner.$player
|
||||
|
||||
this.owner.filter('stop', (danmu) => {
|
||||
switch (danmu.mode) {
|
||||
// 滚动的弹幕
|
||||
case 0:
|
||||
danmu.$ref!.style.left = `${clientWidth}px`
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
})
|
||||
|
||||
this.owner.filter('emit', (danmu) => {
|
||||
danmu.$lastStartTime = Date.now()
|
||||
switch (danmu.mode) {
|
||||
// 滚动的弹幕
|
||||
case 0: {
|
||||
const distance = clientWidth + danmu.$ref!.clientWidth
|
||||
danmu.$ref!.style.left = `${clientWidth}px`
|
||||
danmu.$ref!.style.transform = `translateX(${-distance}px)`
|
||||
danmu.$ref!.style.transition = `transform ${danmu.$restTime}s linear 0s`
|
||||
break
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
continue() {
|
||||
const { clientWidth } = this.owner.$player
|
||||
this.owner.filter('stop', (danmu) => {
|
||||
this.owner.setState(danmu, 'emit') // 转换为emit状态
|
||||
danmu.$lastStartTime = Date.now()
|
||||
switch (danmu.mode) {
|
||||
// 继续滚动的弹幕
|
||||
case 0: {
|
||||
const distance = clientWidth + danmu.$ref!.clientWidth
|
||||
danmu.$ref!.style.transform = `translateX(${-distance}px)`
|
||||
danmu.$ref!.style.transition = `transform ${danmu.$restTime}s linear 0s`
|
||||
break
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
})
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
suspend() {
|
||||
const { clientWidth } = this.owner.$player
|
||||
this.owner.filter('emit', (danmu) => {
|
||||
this.owner.setState(danmu, 'stop') // 转换为stop状态
|
||||
switch (danmu.mode) {
|
||||
// 停止滚动的弹幕
|
||||
case 0: {
|
||||
const translateX = clientWidth - (this.owner.getLeft(danmu.$ref!) - this.owner.getLeft(this.owner.$player))
|
||||
danmu.$ref!.style.transform = `translateX(${-translateX}px)`
|
||||
danmu.$ref!.style.transition = 'transform 0s linear 0s'
|
||||
break
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
})
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
prepare(danmu: DanmuItem, operation: FrameOperation) {
|
||||
const owner = this.owner
|
||||
const ref = owner.$ref
|
||||
operation.danmu = danmu
|
||||
operation.ref = ref
|
||||
danmu.$ref = ref
|
||||
ref.textContent = danmu.text
|
||||
owner.$danmuku.appendChild(ref)
|
||||
ref.style.opacity = owner.option.opacity as unknown as string
|
||||
ref.style.fontSize = `${owner.fontSize}px`
|
||||
ref.style.color = danmu.color
|
||||
ref.style.border = danmu.border ? `1px solid ${danmu.color}` : null as unknown as string
|
||||
ref.style.backgroundColor = danmu.border ? 'rgb(0 0 0 / 50%)' : null as unknown as string
|
||||
owner.utils.setStyles(ref, danmu.style)
|
||||
return ref
|
||||
}
|
||||
|
||||
place(danmu: DanmuItem, ref: HTMLDivElement, top: number, distance: number, clientWidth: number) {
|
||||
ref.style.top = `${top}px`
|
||||
ref.style.visibility = 'visible'
|
||||
ref.dataset.mode = danmu.mode as unknown as string
|
||||
ref.dataset.id = danmu.id || ''
|
||||
switch (danmu.mode) {
|
||||
case 0:
|
||||
ref.style.left = `${clientWidth}px`
|
||||
ref.style.marginLeft = '0px'
|
||||
ref.style.transform = `translateX(${-distance}px)`
|
||||
ref.style.transition = `transform ${danmu.$restTime}s linear 0s`
|
||||
break
|
||||
case 1:
|
||||
case 2:
|
||||
ref.style.left = '50%'
|
||||
ref.style.marginLeft = `-${ref.clientWidth / 2}px`
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
release(operation: FrameOperation) {
|
||||
const { danmu, ref } = operation
|
||||
if (ref && danmu!.$ref === ref) {
|
||||
ref.style.cssText = this.owner.constructor.cssText
|
||||
ref.style.visibility = 'hidden'
|
||||
this.owner.$refs.push(ref)
|
||||
danmu!.$ref = null
|
||||
}
|
||||
operation.ref = null
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.destroy()
|
||||
this.owner.$refs = []
|
||||
this.owner.$danmuku.textContent = ''
|
||||
}
|
||||
|
||||
destroy() {
|
||||
for (const node of this.nodes) {
|
||||
if (node.parentElement)
|
||||
node.parentElement.removeChild(node)
|
||||
}
|
||||
for (const danmu of this.owner.queue) danmu.$ref = null
|
||||
this.owner.$refs.length = 0
|
||||
this.nodes.clear()
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user