Toggle navigation
Toggle navigation
This project
Loading...
Sign in
Hooke
/
lls_program
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Builds
Commits
Issue Boards
Authored by
hookehuyr
2025-10-29 09:40:46 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
2d9282aca4f6913a1bae3f0d64164705e0454997
2d9282ac
1 parent
2818b5ec
fix(弹幕组件): 增强弹幕宽度测量逻辑和默认值处理
改进弹幕宽度测量功能,增加重试机制和更保守的默认值计算 优化动画启动时机,确保宽度测量完成后再开始
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
40 additions
and
9 deletions
src/components/NativeDanmuComponent.vue
src/components/NativeDanmuComponent.vue
View file @
2d9282a
...
...
@@ -105,9 +105,16 @@ const WINDOW_WIDTH = SYSTEM_INFO.windowWidth
// px 转 rpx
const toRpx = (px) => (px * CONTAINER_WIDTH) / WINDOW_WIDTH
// 获取弹幕宽度
(rpx)
// 获取弹幕宽度
- 增强版,提供更安全的默认值
const getDanmuWidth = (danmu) => {
return danmu?.widthRpx && danmu.widthRpx > 0 ? danmu.widthRpx : DANMU_WIDTH
if (danmu.widthRpx && danmu.widthRpx > 0) {
return danmu.widthRpx
}
// 如果没有测量到宽度,使用更保守的默认值
// 根据内容长度动态估算,避免过短导致重叠
const contentLength = danmu.data?.familyName?.length || 0
const estimatedWidth = Math.max(DANMU_WIDTH, contentLength * 30 + 100) // 每字符约30rpx + 100rpx边距
return Math.min(estimatedWidth, DANMU_WIDTH * 2) // 最大不超过2倍默认宽度
}
// 重新计算时长,保证速度一致
const recalculateDuration = (danmu) => {
...
...
@@ -115,18 +122,37 @@ const recalculateDuration = (danmu) => {
const totalDistance = CONTAINER_WIDTH + width + EXTRA_DISTANCE
danmu.duration = (totalDistance / (props.danmuSpeed * 0.6)) * 1000
}
// 测量弹幕真实宽度(px),存为 rpx
const measureDanmuWidth = (danmu) => new Promise((resolve) => {
// 测量弹幕真实宽度(px),存为 rpx - 增强版,支持重试和更保守的默认值
const measureDanmuWidth = (danmu, retryCount = 0) => new Promise((resolve) => {
const maxRetries = 3
const retryDelay = 50 // 50ms 重试间隔
try {
const selector = `#danmu-${danmu.id} .danmu-content`
Taro.createSelectorQuery().select(selector).boundingClientRect(rect => {
if (rect && rect.width) {
if (rect && rect.width
&& rect.width > 0
) {
danmu.widthRpx = toRpx(rect.width)
resolve(getDanmuWidth(danmu))
} else if (retryCount < maxRetries) {
// 测量失败,延迟重试
setTimeout(() => {
measureDanmuWidth(danmu, retryCount + 1).then(resolve)
}, retryDelay)
} else {
// 重试失败,使用更保守的默认宽度(比实际内容更大)
danmu.widthRpx = DANMU_WIDTH * 1.5 // 使用1.5倍默认宽度作为安全值
resolve(getDanmuWidth(danmu))
}
resolve(getDanmuWidth(danmu))
}).exec()
} catch (e) {
resolve(getDanmuWidth(danmu))
if (retryCount < maxRetries) {
setTimeout(() => {
measureDanmuWidth(danmu, retryCount + 1).then(resolve)
}, retryDelay)
} else {
danmu.widthRpx = DANMU_WIDTH * 1.5
resolve(getDanmuWidth(danmu))
}
}
})
...
...
@@ -168,7 +194,7 @@ const getDanmuStyle = (danmu, trackIndex) => {
return {
transform: `translateX(${danmu.x}rpx)`,
transition: danmu.isMoving ?
`transform ${(danmu.remainingDuration ?? danmu.duration)}ms linear`
: 'none',
transition: danmu.isMoving ?
'transform ' + (danmu.remainingDuration ?? danmu.duration) + 'ms linear'
: 'none',
opacity: danmu.opacity || 1,
// 明确设置垂直位置
position: 'absolute',
...
...
@@ -279,12 +305,17 @@ const addDanmuToTrack = (danmu, targetTrack = null, options = {}) => {
track.danmus.push(danmu)
track.lastDanmuTime = Date.now()
// 启动弹幕动画
// 启动弹幕动画
- 确保宽度测量完成后再开始
nextTick(async () => {
// 等待宽度测量完成,确保获得准确宽度
await measureDanmuWidth(danmu)
recalculateDuration(danmu)
// 重置起始时间,保证时长重新计算后动画正确
danmu.startTime = Date.now()
// 再次等待一个 tick,确保 DOM 完全更新
await nextTick()
startDanmuAnimation(danmu, track)
})
...
...
Please
register
or
login
to post a comment