fix(cp活动): 修复苹果端奖励滚动动画闪烁问题
This commit is contained in:
parent
07afff8cf8
commit
55d49d026f
@ -259,15 +259,9 @@
|
||||
|
||||
<!-- 奖励 -->
|
||||
<div class="reward-wrapper">
|
||||
<div
|
||||
style="height: 100%; display: flex; align-items: center; overflow: hidden"
|
||||
>
|
||||
<div ref="rewardViewportRef" class="reward-scroll-viewport">
|
||||
<!-- 滚动容器 -->
|
||||
<div
|
||||
v-if="rewardList.length"
|
||||
class="scroll-wrapper"
|
||||
:class="{ 'scroll-wrapper-active': scrollReady }"
|
||||
>
|
||||
<div v-if="rewardList.length" class="scroll-wrapper">
|
||||
<!-- 3套内容,减少 iOS WebView 动画循环边界闪烁 -->
|
||||
<div class="scroll-content" v-for="value in 3" :key="value">
|
||||
<div
|
||||
@ -358,7 +352,7 @@ const props = defineProps({
|
||||
},
|
||||
})
|
||||
|
||||
const scrollReady = ref(false)
|
||||
const rewardViewportRef = ref(null)
|
||||
|
||||
const rewardList = computed(() => {
|
||||
return Array.isArray(props.rewards?.activityRewardProps) ? props.rewards.activityRewardProps : []
|
||||
@ -388,6 +382,9 @@ const clickReward = (item) => {
|
||||
topRewardShow.value = true // 显示奖品
|
||||
}
|
||||
let rewardRestartTimer = null
|
||||
let rewardAnimationFrame = null
|
||||
let rewardLastFrameTime = 0
|
||||
let rewardLoopDistance = 0
|
||||
|
||||
const waitForLayoutFrame = () => {
|
||||
return new Promise((resolve) => {
|
||||
@ -406,13 +403,52 @@ const restartRewardScroll = async () => {
|
||||
if (rewardRestartTimer) {
|
||||
clearTimeout(rewardRestartTimer)
|
||||
}
|
||||
if (rewardAnimationFrame) {
|
||||
cancelAnimationFrame(rewardAnimationFrame)
|
||||
rewardAnimationFrame = null
|
||||
}
|
||||
|
||||
scrollReady.value = false
|
||||
await nextTick()
|
||||
|
||||
rewardRestartTimer = setTimeout(async () => {
|
||||
await waitForLayoutFrame()
|
||||
scrollReady.value = rewardList.value.length > 0
|
||||
const viewport = rewardViewportRef.value
|
||||
if (!viewport || !rewardList.value.length) {
|
||||
rewardRestartTimer = null
|
||||
return
|
||||
}
|
||||
|
||||
const scrollCopies = viewport.querySelectorAll('.scroll-content')
|
||||
if (scrollCopies.length < 2) {
|
||||
rewardRestartTimer = null
|
||||
return
|
||||
}
|
||||
|
||||
rewardLoopDistance =
|
||||
Math.abs(scrollCopies[1].offsetLeft - scrollCopies[0].offsetLeft) ||
|
||||
scrollCopies[0].scrollWidth
|
||||
|
||||
if (!rewardLoopDistance) {
|
||||
rewardRestartTimer = null
|
||||
return
|
||||
}
|
||||
|
||||
viewport.scrollLeft = 0
|
||||
rewardLastFrameTime = performance.now()
|
||||
|
||||
const step = (now) => {
|
||||
const elapsed = now - rewardLastFrameTime
|
||||
rewardLastFrameTime = now
|
||||
const distancePerMs = rewardLoopDistance / 8000
|
||||
const nextScrollLeft = viewport.scrollLeft + distancePerMs * elapsed
|
||||
|
||||
viewport.scrollLeft =
|
||||
nextScrollLeft >= rewardLoopDistance ? nextScrollLeft - rewardLoopDistance : nextScrollLeft
|
||||
|
||||
rewardAnimationFrame = requestAnimationFrame(step)
|
||||
}
|
||||
|
||||
rewardAnimationFrame = requestAnimationFrame(step)
|
||||
rewardRestartTimer = null
|
||||
}, 80)
|
||||
}
|
||||
@ -433,6 +469,10 @@ onUnmounted(() => {
|
||||
clearTimeout(rewardRestartTimer)
|
||||
rewardRestartTimer = null
|
||||
}
|
||||
if (rewardAnimationFrame) {
|
||||
cancelAnimationFrame(rewardAnimationFrame)
|
||||
rewardAnimationFrame = null
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -470,13 +510,17 @@ onUnmounted(() => {
|
||||
right: 15vw;
|
||||
}
|
||||
|
||||
.reward-scroll-viewport {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
.scroll-wrapper {
|
||||
display: flex;
|
||||
width: fit-content;
|
||||
transform: translate3d(0, 0, 0);
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
backface-visibility: hidden;
|
||||
-webkit-backface-visibility: hidden;
|
||||
}
|
||||
|
||||
.scroll-content {
|
||||
@ -485,47 +529,15 @@ onUnmounted(() => {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@keyframes scroll-left {
|
||||
0% {
|
||||
transform: translate3d(0, 0, 0);
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
}
|
||||
100% {
|
||||
transform: translate3d(-33.333333%, 0, 0);
|
||||
-webkit-transform: translate3d(-33.333333%, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes scroll-right {
|
||||
0% {
|
||||
transform: translate3d(0, 0, 0);
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
}
|
||||
100% {
|
||||
transform: translate3d(33.333333%, 0, 0);
|
||||
-webkit-transform: translate3d(33.333333%, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
[dir='ltr'] .scroll-content {
|
||||
margin-left: 4vw;
|
||||
}
|
||||
|
||||
[dir='rtl'] .scroll-content {
|
||||
margin-left: auto;
|
||||
direction: rtl;
|
||||
margin-right: 4vw;
|
||||
}
|
||||
|
||||
[dir='ltr'] .scroll-wrapper-active {
|
||||
animation: scroll-left 8s linear infinite;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
[dir='rtl'] .scroll-wrapper-active {
|
||||
animation: scroll-right 8s linear infinite;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 360px) {
|
||||
* {
|
||||
font-size: 10px;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user