Skip to content

Commit

Permalink
fix(barrage): 解决新增弹幕重叠问题+不同宽度弹幕滚动速度不一致问题+重构taro版本 (#1942)
Browse files Browse the repository at this point in the history
* fix(barrage): 解决不同宽度弹幕滚动速度不一致+新增弹幕重叠+重构taro版本

* fix: 单元测试同步更改

* fix: div标签替换为View,去除console
  • Loading branch information
irisSong authored Feb 6, 2024
1 parent 1415c3c commit daa558d
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 84 deletions.
8 changes: 7 additions & 1 deletion src/packages/barrage/__tests__/barrage.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,14 @@ test('should danmu list props', async () => {

await waitFor(
() => {
const el = container.querySelectorAll('.barrage-item')[0]
const wrapper = container.querySelectorAll('.nut-barrage')[0]

const elScrollDuration = Math.ceil(
(el.clientWidth / wrapper.clientWidth) * 300
)
expect(container.querySelectorAll('.barrage-item')[0]).toHaveStyle({
animationDuration: '300ms',
animationDuration: `${300 + elScrollDuration}ms`,
})
},
{ timeout: 4000 }
Expand Down
2 changes: 1 addition & 1 deletion src/packages/barrage/barrage.scss
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
}

to {
transform: translateX(var(--move-distance));
-webkit-transform: translateX(var(--move-distance));
}
}
}
Expand Down
163 changes: 91 additions & 72 deletions src/packages/barrage/barrage.taro.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React, {
ForwardRefRenderFunction,
useState,
useEffect,
useRef,
useImperativeHandle,
} from 'react'
import { createSelectorQuery } from '@tarojs/taro'

import classNames from 'classnames'

import { View } from '@tarojs/components'
import { BasicComponent, ComponentDefaults } from '@/utils/typings'
import { getRectByTaro } from '@/utils/get-rect-by-taro'

export interface BarrageProps extends BasicComponent {
list: Array<string>
Expand All @@ -18,7 +18,6 @@ export interface BarrageProps extends BasicComponent {
rows: number
gapY: number
}

const defaultProps = {
...ComponentDefaults,
list: [],
Expand Down Expand Up @@ -47,98 +46,118 @@ const InternalBarrage: ForwardRefRenderFunction<
...defaultProps,
...props,
}
const [styleList, setStyleList] = useState<any[]>([])
const [baItemList, setBaItemList] = useState(list)
const barrageListSet = useRef<any>(list)

const barrageBody = useRef<HTMLDivElement>(null)
const barrageContainer = useRef<HTMLDivElement>(null)
const timeId = useRef(new Date().getTime())
const barrageCWidth = useRef(0)
const timer = useRef(0)
const index = useRef(0)
const times = useRef<number[]>([])
const historyIndex = useRef(-1)

const classes = classNames(
classPrefix,
{
[`${classPrefix}-body${timeId.current}`]: true,
},
className
)
const classes = classNames(classPrefix, className)

useImperativeHandle(ref, () => ({
add: (word: string) => {
barrageListSet.current = [...barrageListSet.current, word]
run()
const _index = index.current % list.length
if (!loop && index.current === list.length) {
list.splice(list.length, 0, word)
} else {
list.splice(_index, 0, word)
}
},
}))

const getNodeWidth = async (node: Element | null, type = 'width') => {
if (node) {
const refe = await getRectByTaro(node)
return Math.ceil(type === 'height' ? refe.height : refe.width)
}
return 0
}

useEffect(() => {
barrageListSet.current = [...list]
run()
const init = async () => {
if (barrageBody.current) {
barrageCWidth.current = await getNodeWidth(barrageBody.current)
}
}

init()

setTimeout(() => {
barrageBody.current?.style.setProperty(
'--move-distance',
`-${barrageCWidth.current}px`
)
index.current = 0
run()
}, 300)
return () => {
clearInterval(timer.current)
}
}, [list])

const run = () => {
setBaItemList(barrageListSet.current)
barrageListSet.current.forEach((item: any, index: number) => {
getNode(index)
})
clearInterval(timer.current)
let intervalCache = interval
const _index = (loop ? index.current % list.length : index.current) % rows
const result = times.current[_index] - rows * interval
if (result > 0) {
intervalCache += result
}
timer.current = window.setTimeout(() => {
play()
}, intervalCache)
}

const getNode = (index: number) => {
const query = createSelectorQuery()
setTimeout(() => {
let width = 100
query
.select(`.${classPrefix}-body${timeId.current}`)
.boundingClientRect((rec: any) => {
width = rec.width || 300
})

query
.select(`.${classPrefix}-item${index}`)
.boundingClientRect((recs: any) => {
const height = recs.height
const nodeTop = `${(index % rows) * (height + gapY) + 20}px`
styleInfo(index, nodeTop, width)
})
.exec()
}, 500)
}
const play = async () => {
if (!loop && index.current >= list.length) {
return
}

const styleInfo = (index: number, nodeTop: string, width: number) => {
const timeIndex = index - rows > 0 ? index - rows : 0
const list = styleList
const time = list[timeIndex] ? Number(list[timeIndex]['--time']) : 0
const obj = {
top: nodeTop,
'--time': `${interval * index + time}`,
animationDuration: `${duration}ms`,
animationIterationCount: `${loop ? 'infinite' : 1}`,
animationDelay: `${interval * index + time}ms`,
'--move-distance': `-${width}px`,
const _index = loop ? index.current % list.length : index.current
const el = document.createElement(`View`)

let currentIndex = _index % rows
if (
currentIndex <= historyIndex.current ||
(historyIndex.current === 3 && currentIndex !== 0) ||
Math.abs(currentIndex - historyIndex.current) !== 1
) {
currentIndex =
historyIndex.current + 1 >= rows ? 0 : historyIndex.current + 1
}
historyIndex.current = currentIndex

el.innerHTML = list[_index] as string
el.classList.add('barrage-item')
;(barrageContainer.current as HTMLDivElement).appendChild(el)

try {
const width = await getNodeWidth(el)
const height = await getNodeWidth(el, 'height')
el.classList.add('move')
const elScrollDuration = (width / barrageCWidth.current) * duration
times.current[currentIndex] = Math.ceil(elScrollDuration)
el.style.animationDuration = `${(duration + elScrollDuration).toFixed(
2
)}ms`
el.style.top = `${currentIndex * (height + gapY) + 20}px`
el.style.width = `${width}px`
} catch (error) {
console.log('异常自动流转到下一个')
}
list.push(obj)
setStyleList([...list])
el.addEventListener('animationend', () => {
;(barrageContainer.current as HTMLDivElement).removeChild(el)
})
index.current++
run()
}

return (
<div className={classes} ref={barrageBody} {...restProps}>
<div ref={barrageContainer} className="bContainer">
{baItemList.map((item: any, index: number) => {
return (
<div
className={`barrage-item ${classPrefix}-item${index} move`}
style={styleList[index]}
key={index}
>
{item.length > 8 ? `${item.substr(0, 8)}...` : item}
</div>
)
})}
</div>
</div>
<View className={classes} ref={barrageBody} {...restProps}>
<View ref={barrageContainer} className="bContainer" />
</View>
)
}

Expand Down
30 changes: 27 additions & 3 deletions src/packages/barrage/barrage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ const InternalBarrage: ForwardRefRenderFunction<
const barrageCWidth = useRef(0)
const timer = useRef(0)
const index = useRef(0)
const times = useRef<number[]>([])
const historyIndex = useRef(-1)

const classes = classNames(classPrefix, className)

Expand Down Expand Up @@ -82,27 +84,49 @@ const InternalBarrage: ForwardRefRenderFunction<

const run = () => {
clearInterval(timer.current)
let intervalCache = interval
const _index = (loop ? index.current % list.length : index.current) % rows
const result = times.current[_index] - rows * interval
if (result > 0) {
intervalCache += result
}
timer.current = window.setTimeout(() => {
play()
}, interval)
}, intervalCache)
}

const play = () => {
if (!loop && index.current >= list.length) {
return
}

const _index = loop ? index.current % list.length : index.current
const el = document.createElement(`div`)

let currentIndex = _index % rows
if (
currentIndex <= historyIndex.current ||
(historyIndex.current === 3 && currentIndex !== 0) ||
Math.abs(currentIndex - historyIndex.current) !== 1
) {
currentIndex =
historyIndex.current + 1 >= rows ? 0 : historyIndex.current + 1
}
historyIndex.current = currentIndex

el.innerHTML = list[_index] as string
el.classList.add('barrage-item')
;(barrageContainer.current as HTMLDivElement).appendChild(el)

const width = el.offsetWidth
const height = el.offsetHeight
el.classList.add('move')
el.style.animationDuration = `${duration}ms`
el.style.top = `${(_index % rows) * (height + gapY) + 20}px`
const elScrollDuration = Math.ceil(
(width / barrageCWidth.current) * duration
)
times.current[currentIndex] = elScrollDuration
el.style.animationDuration = `${duration + elScrollDuration}ms`
el.style.top = `${currentIndex * (height + gapY) + 20}px`
el.style.width = `${width}px`

el.addEventListener('animationend', () => {
Expand Down
8 changes: 4 additions & 4 deletions src/packages/barrage/demo.taro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,23 @@ interface T {
const BarrageDemo = () => {
const [translated] = useTranslate<T>({
'zh-CN': {
ed8c172b: '画美不看',
ed8c172b: '画美不看画美不看画美不看画美不看',
ae9cd4a0: '不明觉厉',
ab05020c: '喜大普奔',
bc555a83: '男默女泪',
'4d14b3e0': '累觉不爱',
'448f995e': '爷青结-',
'448f995e': '爷青结',
'75ca4f92': '随机——',
'84aa6bce': '基础用法',
'3d9b2794': '随机添加',
},
'zh-TW': {
ed8c172b: '畫美不看',
ed8c172b: '畫美不看畫美不看畫美不看畫美不看',
ae9cd4a0: '不明覺厲',
ab05020c: '喜大普奔',
bc555a83: '男默女淚',
'4d14b3e0': '累覺不愛',
'448f995e': '爺青結-',
'448f995e': '爺青結',
'75ca4f92': '隨機——',
'84aa6bce': '基礎用法',
'3d9b2794': '隨機添加',
Expand Down
6 changes: 3 additions & 3 deletions src/packages/barrage/demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const BarrageDemo = () => {
ab05020c: '喜大普奔',
bc555a83: '男默女泪',
'4d14b3e0': '累觉不爱',
'448f995e': '爷青结-',
'448f995e': '爷青结',
'75ca4f92': '随机——',
'84aa6bce': '基础用法',
'3d9b2794': '随机添加',
Expand All @@ -39,7 +39,7 @@ const BarrageDemo = () => {
ab05020c: '喜大普奔',
bc555a83: '男默女淚',
'4d14b3e0': '累覺不愛',
'448f995e': '爺青結-',
'448f995e': '爺青結',
'75ca4f92': '隨機——',
'84aa6bce': '基礎用法',
'3d9b2794': '隨機添加',
Expand All @@ -50,7 +50,7 @@ const BarrageDemo = () => {
ab05020c: 'Super Plus enjoy',
bc555a83: 'male silent female tears',
'4d14b3e0': 'Tired of not loving',
'448f995e': 'Ye Qing knot-',
'448f995e': 'Ye Qing knot',
'75ca4f92': 'random--',
'84aa6bce': 'Basic usage',
'3d9b2794': 'add randomly',
Expand Down

0 comments on commit daa558d

Please sign in to comment.