fix(弹幕组件): 修复低端机弹幕突然消失的问题
This commit is contained in:
parent
0bb4b13586
commit
54e09023f0
@ -1,6 +1,10 @@
|
|||||||
<!-- Barrage.vue 优化版 -->
|
<!-- Barrage.vue 优化版 -->
|
||||||
<template>
|
<template>
|
||||||
<div ref="containerRef" class="barrage-root" :class="{ 'barrage-lite': liteAnimations }">
|
<div
|
||||||
|
ref="containerRef"
|
||||||
|
class="barrage-root"
|
||||||
|
:class="{ 'barrage-lite': liteAnimations, 'barrage-paused': isBarragePaused }"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(track, index) in visibleTracks"
|
v-for="(track, index) in visibleTracks"
|
||||||
:key="index"
|
:key="index"
|
||||||
@ -87,6 +91,7 @@ const tracks = ref([[], []])
|
|||||||
const containerRef = ref(null)
|
const containerRef = ref(null)
|
||||||
const idCounter = ref(0)
|
const idCounter = ref(0)
|
||||||
const currentIndex = ref(0)
|
const currentIndex = ref(0)
|
||||||
|
const isBarragePaused = ref(false)
|
||||||
const liteAnimations = shouldUseLiteAnimations()
|
const liteAnimations = shouldUseLiteAnimations()
|
||||||
const visibleTracks = computed(() => tracks.value.filter((track) => track.length > 0))
|
const visibleTracks = computed(() => tracks.value.filter((track) => track.length > 0))
|
||||||
const effectiveMaxItems = computed(() => (liteAnimations ? Math.min(props.maxItems, 1) : props.maxItems))
|
const effectiveMaxItems = computed(() => (liteAnimations ? Math.min(props.maxItems, 1) : props.maxItems))
|
||||||
@ -186,7 +191,7 @@ function getNextBarrage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function canRunBarrage() {
|
function canRunBarrage() {
|
||||||
return isPageVisible && isInViewport && props.barrageList.length > 0
|
return !isBarragePaused.value && isPageVisible && isInViewport && props.barrageList.length > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopBarrage(clearTracks = false) {
|
function stopBarrage(clearTracks = false) {
|
||||||
@ -218,9 +223,24 @@ function restartBarrage(clearTracks = false) {
|
|||||||
startBarrage()
|
startBarrage()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function pauseBarrage(clearTracks = false) {
|
||||||
|
isBarragePaused.value = true
|
||||||
|
stopBarrage(clearTracks)
|
||||||
|
}
|
||||||
|
|
||||||
|
function resumeBarrage() {
|
||||||
|
isBarragePaused.value = false
|
||||||
|
startBarrage()
|
||||||
|
}
|
||||||
|
|
||||||
function handleVisibilityChange() {
|
function handleVisibilityChange() {
|
||||||
isPageVisible = !document.hidden
|
isPageVisible = !document.hidden
|
||||||
restartBarrage(true)
|
if (isPageVisible && isInViewport) {
|
||||||
|
resumeBarrage()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pauseBarrage(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupViewportObserver() {
|
function setupViewportObserver() {
|
||||||
@ -231,7 +251,12 @@ function setupViewportObserver() {
|
|||||||
viewportObserver = new IntersectionObserver(
|
viewportObserver = new IntersectionObserver(
|
||||||
([entry]) => {
|
([entry]) => {
|
||||||
isInViewport = entry?.isIntersecting !== false
|
isInViewport = entry?.isIntersecting !== false
|
||||||
restartBarrage(true)
|
if (isInViewport && isPageVisible) {
|
||||||
|
resumeBarrage()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pauseBarrage(false)
|
||||||
},
|
},
|
||||||
{ rootMargin: '80px 0px', threshold: 0 },
|
{ rootMargin: '80px 0px', threshold: 0 },
|
||||||
)
|
)
|
||||||
@ -262,7 +287,12 @@ watch(
|
|||||||
[() => props.barrageList, () => locale.value],
|
[() => props.barrageList, () => locale.value],
|
||||||
() => {
|
() => {
|
||||||
currentIndex.value = 0
|
currentIndex.value = 0
|
||||||
restartBarrage(true)
|
if (props.barrageList.length === 0) {
|
||||||
|
stopBarrage(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
restartBarrage(false)
|
||||||
},
|
},
|
||||||
{ deep: false },
|
{ deep: false },
|
||||||
)
|
)
|
||||||
@ -300,6 +330,10 @@ watch(
|
|||||||
will-change: auto;
|
will-change: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.barrage-paused .barrage-item {
|
||||||
|
animation-play-state: paused;
|
||||||
|
}
|
||||||
|
|
||||||
.barrage-avatar {
|
.barrage-avatar {
|
||||||
width: 10vw;
|
width: 10vw;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
<!-- Barrage.vue 优化版 -->
|
<!-- Barrage.vue 优化版 -->
|
||||||
<template>
|
<template>
|
||||||
<div ref="containerRef" class="barrage-root" :class="{ 'barrage-lite': liteAnimations }">
|
<div
|
||||||
|
ref="containerRef"
|
||||||
|
class="barrage-root"
|
||||||
|
:class="{ 'barrage-lite': liteAnimations, 'barrage-paused': isBarragePaused }"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(track, index) in visibleTracks"
|
v-for="(track, index) in visibleTracks"
|
||||||
:key="index"
|
:key="index"
|
||||||
@ -92,6 +96,7 @@ const tracks = ref([[], []])
|
|||||||
const containerRef = ref(null)
|
const containerRef = ref(null)
|
||||||
const idCounter = ref(0)
|
const idCounter = ref(0)
|
||||||
const currentIndex = ref(0)
|
const currentIndex = ref(0)
|
||||||
|
const isBarragePaused = ref(false)
|
||||||
const liteAnimations = shouldUseLiteAnimations()
|
const liteAnimations = shouldUseLiteAnimations()
|
||||||
const visibleTracks = computed(() => tracks.value.filter((track) => track.length > 0))
|
const visibleTracks = computed(() => tracks.value.filter((track) => track.length > 0))
|
||||||
const effectiveMaxItems = computed(() => (liteAnimations ? Math.min(props.maxItems, 1) : props.maxItems))
|
const effectiveMaxItems = computed(() => (liteAnimations ? Math.min(props.maxItems, 1) : props.maxItems))
|
||||||
@ -182,7 +187,7 @@ function getNextBarrage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function canRunBarrage() {
|
function canRunBarrage() {
|
||||||
return isPageVisible && isInViewport && props.barrageList.length > 0
|
return !isBarragePaused.value && isPageVisible && isInViewport && props.barrageList.length > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopBarrage(clearTracks = false) {
|
function stopBarrage(clearTracks = false) {
|
||||||
@ -214,9 +219,24 @@ function restartBarrage(clearTracks = false) {
|
|||||||
startBarrage()
|
startBarrage()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function pauseBarrage(clearTracks = false) {
|
||||||
|
isBarragePaused.value = true
|
||||||
|
stopBarrage(clearTracks)
|
||||||
|
}
|
||||||
|
|
||||||
|
function resumeBarrage() {
|
||||||
|
isBarragePaused.value = false
|
||||||
|
startBarrage()
|
||||||
|
}
|
||||||
|
|
||||||
function handleVisibilityChange() {
|
function handleVisibilityChange() {
|
||||||
isPageVisible = !document.hidden
|
isPageVisible = !document.hidden
|
||||||
restartBarrage(true)
|
if (isPageVisible && isInViewport) {
|
||||||
|
resumeBarrage()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pauseBarrage(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupViewportObserver() {
|
function setupViewportObserver() {
|
||||||
@ -227,7 +247,12 @@ function setupViewportObserver() {
|
|||||||
viewportObserver = new IntersectionObserver(
|
viewportObserver = new IntersectionObserver(
|
||||||
([entry]) => {
|
([entry]) => {
|
||||||
isInViewport = entry?.isIntersecting !== false
|
isInViewport = entry?.isIntersecting !== false
|
||||||
restartBarrage(true)
|
if (isInViewport && isPageVisible) {
|
||||||
|
resumeBarrage()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pauseBarrage(false)
|
||||||
},
|
},
|
||||||
{ rootMargin: '80px 0px', threshold: 0 },
|
{ rootMargin: '80px 0px', threshold: 0 },
|
||||||
)
|
)
|
||||||
@ -258,7 +283,12 @@ watch(
|
|||||||
[() => props.barrageList, () => locale.value],
|
[() => props.barrageList, () => locale.value],
|
||||||
() => {
|
() => {
|
||||||
currentIndex.value = 0
|
currentIndex.value = 0
|
||||||
restartBarrage(true)
|
if (props.barrageList.length === 0) {
|
||||||
|
stopBarrage(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
restartBarrage(false)
|
||||||
},
|
},
|
||||||
{ deep: false },
|
{ deep: false },
|
||||||
)
|
)
|
||||||
@ -296,6 +326,10 @@ watch(
|
|||||||
will-change: auto;
|
will-change: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.barrage-paused .barrage-item {
|
||||||
|
animation-play-state: paused;
|
||||||
|
}
|
||||||
|
|
||||||
.barrage-avatar {
|
.barrage-avatar {
|
||||||
width: 10vw;
|
width: 10vw;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
<!-- Barrage.vue 优化版 -->
|
<!-- Barrage.vue 优化版 -->
|
||||||
<template>
|
<template>
|
||||||
<div ref="containerRef" class="barrage-root" :class="{ 'barrage-lite': liteAnimations }">
|
<div
|
||||||
|
ref="containerRef"
|
||||||
|
class="barrage-root"
|
||||||
|
:class="{ 'barrage-lite': liteAnimations, 'barrage-paused': isBarragePaused }"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(track, index) in visibleTracks"
|
v-for="(track, index) in visibleTracks"
|
||||||
:key="index"
|
:key="index"
|
||||||
@ -92,6 +96,7 @@ const tracks = ref([[], []])
|
|||||||
const containerRef = ref(null)
|
const containerRef = ref(null)
|
||||||
const idCounter = ref(0)
|
const idCounter = ref(0)
|
||||||
const currentIndex = ref(0)
|
const currentIndex = ref(0)
|
||||||
|
const isBarragePaused = ref(false)
|
||||||
const liteAnimations = shouldUseLiteAnimations()
|
const liteAnimations = shouldUseLiteAnimations()
|
||||||
const visibleTracks = computed(() => tracks.value.filter((track) => track.length > 0))
|
const visibleTracks = computed(() => tracks.value.filter((track) => track.length > 0))
|
||||||
const effectiveMaxItems = computed(() => (liteAnimations ? Math.min(props.maxItems, 1) : props.maxItems))
|
const effectiveMaxItems = computed(() => (liteAnimations ? Math.min(props.maxItems, 1) : props.maxItems))
|
||||||
@ -182,7 +187,7 @@ function getNextBarrage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function canRunBarrage() {
|
function canRunBarrage() {
|
||||||
return isPageVisible && isInViewport && props.barrageList.length > 0
|
return !isBarragePaused.value && isPageVisible && isInViewport && props.barrageList.length > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopBarrage(clearTracks = false) {
|
function stopBarrage(clearTracks = false) {
|
||||||
@ -214,9 +219,24 @@ function restartBarrage(clearTracks = false) {
|
|||||||
startBarrage()
|
startBarrage()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function pauseBarrage(clearTracks = false) {
|
||||||
|
isBarragePaused.value = true
|
||||||
|
stopBarrage(clearTracks)
|
||||||
|
}
|
||||||
|
|
||||||
|
function resumeBarrage() {
|
||||||
|
isBarragePaused.value = false
|
||||||
|
startBarrage()
|
||||||
|
}
|
||||||
|
|
||||||
function handleVisibilityChange() {
|
function handleVisibilityChange() {
|
||||||
isPageVisible = !document.hidden
|
isPageVisible = !document.hidden
|
||||||
restartBarrage(true)
|
if (isPageVisible && isInViewport) {
|
||||||
|
resumeBarrage()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pauseBarrage(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupViewportObserver() {
|
function setupViewportObserver() {
|
||||||
@ -227,7 +247,12 @@ function setupViewportObserver() {
|
|||||||
viewportObserver = new IntersectionObserver(
|
viewportObserver = new IntersectionObserver(
|
||||||
([entry]) => {
|
([entry]) => {
|
||||||
isInViewport = entry?.isIntersecting !== false
|
isInViewport = entry?.isIntersecting !== false
|
||||||
restartBarrage(true)
|
if (isInViewport && isPageVisible) {
|
||||||
|
resumeBarrage()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pauseBarrage(false)
|
||||||
},
|
},
|
||||||
{ rootMargin: '80px 0px', threshold: 0 },
|
{ rootMargin: '80px 0px', threshold: 0 },
|
||||||
)
|
)
|
||||||
@ -258,7 +283,12 @@ watch(
|
|||||||
[() => props.barrageList, () => locale.value],
|
[() => props.barrageList, () => locale.value],
|
||||||
() => {
|
() => {
|
||||||
currentIndex.value = 0
|
currentIndex.value = 0
|
||||||
restartBarrage(true)
|
if (props.barrageList.length === 0) {
|
||||||
|
stopBarrage(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
restartBarrage(false)
|
||||||
},
|
},
|
||||||
{ deep: false },
|
{ deep: false },
|
||||||
)
|
)
|
||||||
@ -296,6 +326,10 @@ watch(
|
|||||||
will-change: auto;
|
will-change: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.barrage-paused .barrage-item {
|
||||||
|
animation-play-state: paused;
|
||||||
|
}
|
||||||
|
|
||||||
.barrage-avatar {
|
.barrage-avatar {
|
||||||
width: 10vw;
|
width: 10vw;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
<!-- 告白墙弹幕 -->
|
<!-- 告白墙弹幕 -->
|
||||||
<template>
|
<template>
|
||||||
<div ref="containerRef" class="barrage-root" :class="{ 'barrage-lite': liteAnimations }">
|
<div
|
||||||
|
ref="containerRef"
|
||||||
|
class="barrage-root"
|
||||||
|
:class="{ 'barrage-lite': liteAnimations, 'barrage-paused': isBarragePaused }"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(track, index) in visibleTracks"
|
v-for="(track, index) in visibleTracks"
|
||||||
:key="index"
|
:key="index"
|
||||||
@ -127,6 +131,7 @@ const tracks = ref([[], []])
|
|||||||
const containerRef = ref(null)
|
const containerRef = ref(null)
|
||||||
const idCounter = ref(0)
|
const idCounter = ref(0)
|
||||||
const currentIndex = ref(0)
|
const currentIndex = ref(0)
|
||||||
|
const isBarragePaused = ref(false)
|
||||||
const liteAnimations = shouldUseLiteAnimations()
|
const liteAnimations = shouldUseLiteAnimations()
|
||||||
const visibleTracks = computed(() => tracks.value.filter((track) => track.length > 0))
|
const visibleTracks = computed(() => tracks.value.filter((track) => track.length > 0))
|
||||||
const effectiveMaxItems = computed(() => (liteAnimations ? Math.min(props.maxItems, 1) : props.maxItems))
|
const effectiveMaxItems = computed(() => (liteAnimations ? Math.min(props.maxItems, 1) : props.maxItems))
|
||||||
@ -204,7 +209,7 @@ function getNextBarrage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function canRunBarrage() {
|
function canRunBarrage() {
|
||||||
return isPageVisible && isInViewport && props.barrageList.length > 0
|
return !isBarragePaused.value && isPageVisible && isInViewport && props.barrageList.length > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopBarrage(clearTracks = false) {
|
function stopBarrage(clearTracks = false) {
|
||||||
@ -236,9 +241,24 @@ function restartBarrage(clearTracks = false) {
|
|||||||
startBarrage()
|
startBarrage()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function pauseBarrage(clearTracks = false) {
|
||||||
|
isBarragePaused.value = true
|
||||||
|
stopBarrage(clearTracks)
|
||||||
|
}
|
||||||
|
|
||||||
|
function resumeBarrage() {
|
||||||
|
isBarragePaused.value = false
|
||||||
|
startBarrage()
|
||||||
|
}
|
||||||
|
|
||||||
function handleVisibilityChange() {
|
function handleVisibilityChange() {
|
||||||
isPageVisible = !document.hidden
|
isPageVisible = !document.hidden
|
||||||
restartBarrage(true)
|
if (isPageVisible && isInViewport) {
|
||||||
|
resumeBarrage()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pauseBarrage(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupViewportObserver() {
|
function setupViewportObserver() {
|
||||||
@ -249,7 +269,12 @@ function setupViewportObserver() {
|
|||||||
viewportObserver = new IntersectionObserver(
|
viewportObserver = new IntersectionObserver(
|
||||||
([entry]) => {
|
([entry]) => {
|
||||||
isInViewport = entry?.isIntersecting !== false
|
isInViewport = entry?.isIntersecting !== false
|
||||||
restartBarrage(true)
|
if (isInViewport && isPageVisible) {
|
||||||
|
resumeBarrage()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pauseBarrage(false)
|
||||||
},
|
},
|
||||||
{ rootMargin: '80px 0px', threshold: 0 },
|
{ rootMargin: '80px 0px', threshold: 0 },
|
||||||
)
|
)
|
||||||
@ -280,7 +305,12 @@ watch(
|
|||||||
() => props.barrageList,
|
() => props.barrageList,
|
||||||
() => {
|
() => {
|
||||||
currentIndex.value = 0
|
currentIndex.value = 0
|
||||||
restartBarrage(true)
|
if (props.barrageList.length === 0) {
|
||||||
|
stopBarrage(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
restartBarrage(false)
|
||||||
},
|
},
|
||||||
{ deep: false },
|
{ deep: false },
|
||||||
)
|
)
|
||||||
@ -324,6 +354,10 @@ watch(
|
|||||||
will-change: auto;
|
will-change: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.barrage-paused .barrage-item {
|
||||||
|
animation-play-state: paused;
|
||||||
|
}
|
||||||
|
|
||||||
.avatar-pair {
|
.avatar-pair {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user