feat(弹幕组件): 优化弹幕循环逻辑和持续性
增强弹幕组件的循环逻辑,确保在没有数据时自动重新获取 调整弹幕轨道数量和容器高度以优化显示效果
Showing
2 changed files
with
29 additions
and
15 deletions
| ... | @@ -387,7 +387,7 @@ const startDanmuAnimation = (danmu, track) => { | ... | @@ -387,7 +387,7 @@ const startDanmuAnimation = (danmu, track) => { |
| 387 | animationTimers.value.set(danmu.id, timer) | 387 | animationTimers.value.set(danmu.id, timer) |
| 388 | } | 388 | } |
| 389 | 389 | ||
| 390 | -// 重置弹幕位置实现循环 | 390 | +// 重置弹幕位置实现循环 - 增强持续性 |
| 391 | const resetDanmuForLoop = (danmu, track) => { | 391 | const resetDanmuForLoop = (danmu, track) => { |
| 392 | if (!isPlaying.value) return | 392 | if (!isPlaying.value) return |
| 393 | 393 | ||
| ... | @@ -395,10 +395,20 @@ const resetDanmuForLoop = (danmu, track) => { | ... | @@ -395,10 +395,20 @@ const resetDanmuForLoop = (danmu, track) => { |
| 395 | danmu.isMoving = false | 395 | danmu.isMoving = false |
| 396 | danmu.opacity = 1 | 396 | danmu.opacity = 1 |
| 397 | 397 | ||
| 398 | - // 切换下一条数据,遵循首轮不重复规则 | 398 | + // 切换下一条数据,确保持续循环 |
| 399 | const nextData = getNextUnusedDanmu() | 399 | const nextData = getNextUnusedDanmu() |
| 400 | if (nextData) { | 400 | if (nextData) { |
| 401 | danmu.data = nextData | 401 | danmu.data = nextData |
| 402 | + } else { | ||
| 403 | + // 如果没有数据,重新获取弹幕数据 | ||
| 404 | + console.log('弹幕数据不足,尝试重新获取') | ||
| 405 | + fetchDanmuData().then(() => { | ||
| 406 | + const retryData = getNextUnusedDanmu() | ||
| 407 | + if (retryData) { | ||
| 408 | + danmu.data = retryData | ||
| 409 | + } | ||
| 410 | + }) | ||
| 411 | + return | ||
| 402 | } | 412 | } |
| 403 | 413 | ||
| 404 | // 复位到右侧并重新计时 | 414 | // 复位到右侧并重新计时 |
| ... | @@ -407,7 +417,11 @@ const resetDanmuForLoop = (danmu, track) => { | ... | @@ -407,7 +417,11 @@ const resetDanmuForLoop = (danmu, track) => { |
| 407 | track.lastDanmuTime = Date.now() | 417 | track.lastDanmuTime = Date.now() |
| 408 | 418 | ||
| 409 | // 重新启动动画(无缝继续) | 419 | // 重新启动动画(无缝继续) |
| 410 | - nextTick(() => { | 420 | + nextTick(async () => { |
| 421 | + // 重新测量宽度,确保准确性 | ||
| 422 | + await measureDanmuWidth(danmu) | ||
| 423 | + recalculateDuration(danmu) | ||
| 424 | + danmu.startTime = Date.now() | ||
| 411 | startDanmuAnimation(danmu, track) | 425 | startDanmuAnimation(danmu, track) |
| 412 | }) | 426 | }) |
| 413 | } | 427 | } |
| ... | @@ -441,7 +455,7 @@ const resetDanmuIndex = () => { | ... | @@ -441,7 +455,7 @@ const resetDanmuIndex = () => { |
| 441 | isFirstRound = true | 455 | isFirstRound = true |
| 442 | } | 456 | } |
| 443 | 457 | ||
| 444 | -// 获取下一个未使用的弹幕数据 | 458 | +// 获取下一个弹幕数据 - 优化循环逻辑 |
| 445 | const getNextUnusedDanmu = () => { | 459 | const getNextUnusedDanmu = () => { |
| 446 | if (!familyDanmus.value || familyDanmus.value.length === 0) { | 460 | if (!familyDanmus.value || familyDanmus.value.length === 0) { |
| 447 | return null | 461 | return null |
| ... | @@ -462,20 +476,17 @@ const getNextUnusedDanmu = () => { | ... | @@ -462,20 +476,17 @@ const getNextUnusedDanmu = () => { |
| 462 | currentDanmuIndex++ | 476 | currentDanmuIndex++ |
| 463 | } | 477 | } |
| 464 | 478 | ||
| 465 | - // 第一轮遍历完成 | 479 | + // 第一轮遍历完成,开始无限循环 |
| 466 | isFirstRound = false | 480 | isFirstRound = false |
| 467 | currentDanmuIndex = 0 | 481 | currentDanmuIndex = 0 |
| 468 | usedDanmuIds.clear() | 482 | usedDanmuIds.clear() |
| 483 | + console.log('弹幕第一轮完成,开始无限循环') | ||
| 469 | } | 484 | } |
| 470 | 485 | ||
| 471 | - // 第一轮遍历完成后,重新开始循环 | 486 | + // 无限循环模式 - 确保永远有弹幕 |
| 472 | - if (!isFirstRound) { | ||
| 473 | const danmuData = familyDanmus.value[currentDanmuIndex % familyDanmus.value.length] | 487 | const danmuData = familyDanmus.value[currentDanmuIndex % familyDanmus.value.length] |
| 474 | - currentDanmuIndex++ | 488 | + currentDanmuIndex = (currentDanmuIndex + 1) % familyDanmus.value.length |
| 475 | return danmuData | 489 | return danmuData |
| 476 | - } | ||
| 477 | - | ||
| 478 | - return null | ||
| 479 | } | 490 | } |
| 480 | 491 | ||
| 481 | // 发送顺序弹幕 | 492 | // 发送顺序弹幕 |
| ... | @@ -488,7 +499,7 @@ const sendSequentialDanmu = () => { | ... | @@ -488,7 +499,7 @@ const sendSequentialDanmu = () => { |
| 488 | } | 499 | } |
| 489 | } | 500 | } |
| 490 | 501 | ||
| 491 | -// 自动发送弹幕 | 502 | +// 自动发送弹幕 - 增强持续性 |
| 492 | let autoSendTimer = null | 503 | let autoSendTimer = null |
| 493 | const startAutoSend = () => { | 504 | const startAutoSend = () => { |
| 494 | if (autoSendTimer) return | 505 | if (autoSendTimer) return |
| ... | @@ -510,8 +521,11 @@ const startAutoSend = () => { | ... | @@ -510,8 +521,11 @@ const startAutoSend = () => { |
| 510 | const intervalMultiplier = Math.max(1, (6 - availableTrackCount) * 0.2) // 减少间隔倍数 | 521 | const intervalMultiplier = Math.max(1, (6 - availableTrackCount) * 0.2) // 减少间隔倍数 |
| 511 | const dynamicInterval = baseInterval * intervalMultiplier + Math.random() * 300 | 522 | const dynamicInterval = baseInterval * intervalMultiplier + Math.random() * 300 |
| 512 | 523 | ||
| 524 | + // 确保持续循环,即使暂时没有可用轨道也要继续尝试 | ||
| 525 | + if (isPlaying.value) { | ||
| 513 | autoSendTimer = setTimeout(sendNext, dynamicInterval) | 526 | autoSendTimer = setTimeout(sendNext, dynamicInterval) |
| 514 | } | 527 | } |
| 528 | + } | ||
| 515 | 529 | ||
| 516 | // 立即发送第一条弹幕,不等待 | 530 | // 立即发送第一条弹幕,不等待 |
| 517 | sendNext() | 531 | sendNext() | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2025-09-01 13:07:52 | 2 | * @Date: 2025-09-01 13:07:52 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-10-28 16:36:47 | 4 | + * @LastEditTime: 2025-10-29 09:53:38 |
| 5 | * @FilePath: /lls_program/src/pages/FamilyRank/index.vue | 5 | * @FilePath: /lls_program/src/pages/FamilyRank/index.vue |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | --> | 7 | --> |
| ... | @@ -159,9 +159,9 @@ | ... | @@ -159,9 +159,9 @@ |
| 159 | <!-- 隐藏的弹幕组件,在页面加载时就开始滚动 --> | 159 | <!-- 隐藏的弹幕组件,在页面加载时就开始滚动 --> |
| 160 | <view class="danmu-section mt-8" :style="{ visibility: activeTab === 'support' ? 'visible' : 'hidden', position: activeTab === 'support' ? 'static' : 'absolute', top: activeTab === 'support' ? 'auto' : '-9999px' }"> | 160 | <view class="danmu-section mt-8" :style="{ visibility: activeTab === 'support' ? 'visible' : 'hidden', position: activeTab === 'support' ? 'static' : 'absolute', top: activeTab === 'support' ? 'auto' : '-9999px' }"> |
| 161 | <NativeDanmuComponent | 161 | <NativeDanmuComponent |
| 162 | - :container-height="1200" | 162 | + :container-height="1100" |
| 163 | :show-controls="true" | 163 | :show-controls="true" |
| 164 | - :track-count="7" | 164 | + :track-count="5" |
| 165 | @danmu-click="handleDanmuClick" | 165 | @danmu-click="handleDanmuClick" |
| 166 | @danmu-hover="handleDanmuHover" | 166 | @danmu-hover="handleDanmuHover" |
| 167 | ref="danmuRef" | 167 | ref="danmuRef" | ... | ... |
-
Please register or login to post a comment