Compare commits

..

No commits in common. "e29a718b2fa5562f059c463de07dee7c518ce83d" and "4d42d9a6d08c39be90617b465b5f8663e80f6919" have entirely different histories.

2 changed files with 53 additions and 1185 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,24 +1,52 @@
<template>
<scroll-view class="waterfall-scroll" :style="scrollStyle" scroll-x :show-scrollbar="false"
:scroll-left="isIOS ? undefined : scrollLeft" :bounce="false" @scroll="onScroll" @touchstart="onTouchStart"
@touchend="onTouchEnd" @touchcancel="onTouchEnd">
<view ref="waterfallInnerRef" :class="{ 'waterfall-inner': true, 'ios-css-animate': !iosScrollPaused }"
:style="innerStyle">
<view v-for="card in cards" :key="card.id" class="wf-card" :style="cardStyle(card)"
@click="handleCardClick(card)">
<scroll-view
class="waterfall-scroll"
:style="scrollStyle"
scroll-x
:show-scrollbar="false"
:scroll-left="isIOS ? undefined : scrollLeft"
:bounce="false"
@scroll="onScroll"
@touchstart="onTouchStart"
@touchend="onTouchEnd"
@touchcancel="onTouchEnd"
>
<view
ref="waterfallInnerRef"
:class="{'waterfall-inner': true, 'ios-css-animate': !iosScrollPaused}"
:style="innerStyle"
>
<view
v-for="card in cards"
:key="card.id"
class="wf-card"
:style="cardStyle(card)"
@click="handleCardClick(card)"
>
<!-- 渐变边框光效 -->
<view class="wf-card-border" :style="borderStyle(card)" />
<!-- 封面图 -->
<image v-if="card.coverUrl" class="wf-card-img" :src="card.coverUrl" mode="aspectFill"
:style="{ width: card.w + 'px', height: card.h + 'px', borderRadius: card.radius + 'px' }" />
<image
v-if="card.coverUrl"
class="wf-card-img"
:src="card.coverUrl"
mode="aspectFill"
:style="{ width: card.w + 'px', height: card.h + 'px', borderRadius: card.radius + 'px' }"
/>
<!-- 光波动画层 - 外层 -->
<view class="wf-like-wave wf-like-wave-outer" :class="{ 'wf-like-wave-active': likingMap[card.id] }"
:style="{ width: card.w + 'px', height: card.h + 'px', borderRadius: card.radius + 'px' }" />
<view
class="wf-like-wave wf-like-wave-outer"
:class="{ 'wf-like-wave-active': likingMap[card.id] }"
:style="{ width: card.w + 'px', height: card.h + 'px', borderRadius: card.radius + 'px' }"
/>
<!-- 光波动画层 - 内层 -->
<view class="wf-like-wave wf-like-wave-inner" :class="{ 'wf-like-wave-active': likingMap[card.id] }"
:style="{ width: card.w + 'px', height: card.h + 'px', borderRadius: card.radius + 'px' }" />
<view
class="wf-like-wave wf-like-wave-inner"
:class="{ 'wf-like-wave-active': likingMap[card.id] }"
:style="{ width: card.w + 'px', height: card.h + 'px', borderRadius: card.radius + 'px' }"
/>
<!-- 底部点赞数 -->
<view class="wf-card-footer">
@ -156,10 +184,6 @@ const startAutoScroll = () => {
scrollUpdateTimer = setInterval(() => {
if (!isComponentMounted || userInteracting || isLoadingMore) return
autoScrollPos += AUTO_SCROLL_SPEED_ANDROID
// 0
if (autoScrollPos >= totalWidth.value) {
autoScrollPos = 0
}
scrollLeft.value = autoScrollPos
//
@ -334,13 +358,6 @@ class WaterfallLayout {
// = rowH × 9/16 9:16span
this.colW = Math.round(this.rowH * 4 / 3)
this.curX = 0
// N 5 6 N
this.consecutiveNCount = 0
}
_isNLevel(item) {
const span = item.span != null ? item.span : this._span(item.likes || 0)
return span === 1
}
_cardSize(span) {
@ -375,28 +392,10 @@ class WaterfallLayout {
let i = 0
while (i < remaining.length) {
const rawSpan = remaining[i].span
const isN = remaining[i]._blank ? false : this._isNLevel(remaining[i])
// N 5 6 N 1-2
if (isN && this.consecutiveNCount >= 5) {
const blankCount = Math.random() < 0.5 ? 1 : 2
for (let b = 0; b < blankCount; b++) {
if (sum + 1 <= ROWS) {
remaining.splice(i, 0, { id: idCounter++, span: 1, _blank: true, likes: 0 })
}
}
this.consecutiveNCount = 0
// i break
break
}
// ROWS
if (sum + rawSpan > ROWS) {
i++
// ROWS
if (i >= remaining.length && col.length > 0) {
break
}
continue
}
@ -405,15 +404,6 @@ class WaterfallLayout {
col.push(item)
sum += rawSpan
// N N
if (!item._blank) {
if (this._isNLevel(item)) {
this.consecutiveNCount++
} else {
this.consecutiveNCount = 0
}
}
// ROWS
if (sum >= ROWS) break
}
@ -423,13 +413,6 @@ class WaterfallLayout {
const item = remaining.shift()
col.push(item)
sum = item.span
if (!item._blank) {
if (this._isNLevel(item)) {
this.consecutiveNCount++
} else {
this.consecutiveNCount = 0
}
}
}
colIndex++
@ -454,7 +437,7 @@ class WaterfallLayout {
for (const u of colUsers) {
const span = u.span || 1
const { w, h } = this._cardSize(span)
if (!u._pad && !u._blank) {
if (!u._pad) {
result.push({ ...u, left: colX, top: curY, w, h, radius: 8 })
}
curY += h + this.gap
@ -467,7 +450,6 @@ class WaterfallLayout {
//
compute(users) {
this.curX = 0
this.consecutiveNCount = 0
const columns = this._groupIntoColumns(users)
const result = []
for (const col of columns) {
@ -526,9 +508,9 @@ const cardStyle = (card) => ({
const borderStyle = (card) => ({
position: 'absolute',
inset: `-${BORDER_W}px`,
borderRadius: (card.radius + BORDER_W) + 'px',
background: BORDER_COLORS[Math.abs(card.id) % BORDER_COLORS.length],
inset: `-${BORDER_W}px`,
zIndex: 0,
opacity: 0.85,
})
@ -584,7 +566,7 @@ const batchGetPresignedUrls = async (urls) => {
}
return map
}
} catch (_) { }
} catch (_) {}
return {}
}
@ -659,7 +641,7 @@ const loadUsers = async () => {
span: item.span ?? null,
}
})
allUsers.value = withData
cards.value = layout.compute(withData)
totalWidth.value = layout.getTotalWidth()
@ -749,12 +731,6 @@ const appendMore = async () => {
cards.value = [...cards.value, ...placed]
totalWidth.value = layout.getTotalWidth()
// totalWidth iOS CSS
if (isIOS && !iosScrollPaused.value) {
stopIOSAutoScroll()
startIOSAutoScroll()
}
} else {
//
appendFailed = true
@ -798,7 +774,7 @@ const handleCardClick = (card) => {
});
} else {
//
if (card.id) {
if(card.id){
cardTapTimers[card.id] = setTimeout(() => {
delete cardTapTimers[card.id];
uni.navigateTo({ url: `/pages/asset-detail/asset-detail?asset_id=${card.id}` });
@ -939,7 +915,7 @@ onUnmounted(() => {
try {
uni.offAppShow(onAppShowHandler)
uni.offAppHide(onAppHideHandler)
} catch (_) { }
} catch (_) {}
}
})
@ -1023,11 +999,8 @@ const loadUsersAndStartScroll = () => {
}
@keyframes iosAutoScroll {
/* from { transform: translateX(0); } */
to {
transform: translateX(var(--scroll-dist));
}
to { transform: translateX(var(--scroll-dist)); }
}
.wf-card {
@ -1037,7 +1010,6 @@ const loadUsersAndStartScroll = () => {
transform-origin: top center;
overflow: visible;
pointer-events: visible;
transform: translateZ(0);
}
.wf-card:active {
@ -1047,7 +1019,6 @@ const loadUsersAndStartScroll = () => {
.wf-card-border {
position: absolute;
pointer-events: none;
will-change: opacity;
}
.wf-card-img {
@ -1075,9 +1046,10 @@ const loadUsersAndStartScroll = () => {
.wf-likes-wrap {
background: linear-gradient(to bottom right,
#F0E4B1 0%,
#F08399 50%,
#B94E73 100%);
#F0E4B1 0%,
#F08399 50%,
#B94E73 100%
);
border-radius: 999rpx;
padding: 2rpx 10rpx;
display: flex;
@ -1127,10 +1099,10 @@ const loadUsersAndStartScroll = () => {
transform: scale(1);
opacity: 1;
}
100% {
transform: scale(1.1);
opacity: 0;
}
}
</style>