feat: 添加瀑布流滚动的安卓和ios的判断

This commit is contained in:
zerosaturation 2026-05-09 12:40:39 +08:00
parent b68ca3e7be
commit 5208bde803
2 changed files with 78 additions and 75 deletions

View File

@ -2,8 +2,8 @@
"name" : "TopFans",
"appid" : "__UNI__F199FF4",
"description" : "",
"versionName" : "1.0.3",
"versionCode" : 100,
"versionName" : "1.0.4",
"versionCode" : 101,
"transformPx" : false,
/* 5+App */
"app-plus" : {
@ -23,7 +23,8 @@
"modules" : {
"VideoPlayer" : {},
"Camera" : {},
"Speech" : {}
"Speech" : {},
"Push" : {}
},
/* */
"distribute" : {
@ -70,12 +71,7 @@
"secretkey" : "1i5Aj8FwL3i11LYPeXMRwRWycictWq2X"
}
},
"push" : {
"unipush" : {
"version" : "2",
"offline" : false
}
}
"push" : {}
},
"icons" : {
"android" : {

View File

@ -78,8 +78,8 @@ const GAP = rpx2px(16)
const BORDER_W = rpx2px(2)
const SCALE = 0.9
const ROWS = 4
const AUTO_SCROLL_SPEED = 0.1
const AUTO_RESUME_DELAY = 1000
const AUTO_SCROLL_SPEED = 0.3
const AUTO_RESUME_DELAY = 1500
const PRELOAD_THRESHOLD = rpx2px(300)
// ========== ==========
@ -112,62 +112,34 @@ let rafId = null
let userInteracting = false
let resumeTimer = null
let appendTimer = null //
let autoScrollPos = 0 //
let momentumTimer = null // iOS
let scrollUpdateTimer = null // scrollLeft
const startAutoScroll = () => {
if (!isComponentMounted) {
return
}
// RAF
if (!isComponentMounted) return
if (rafId) {
cafFn(rafId)
rafId = null
}
//
userInteracting = false
autoScrollPos = currentScrollLeft
let lastScrollLeft = 0 //
// 使 scrollLeft
clearInterval(scrollUpdateTimer)
scrollUpdateTimer = setInterval(() => {
if (!isComponentMounted || userInteracting || isLoadingMore) return
autoScrollPos += AUTO_SCROLL_SPEED
scrollLeft.value = autoScrollPos
const step = () => {
if (!isComponentMounted) {
rafId = null
return
}
// RAF
if (!isComponentMounted) {
rafId = null
return
}
if (!userInteracting && !isLoadingMore) {
//
const actualScroll = scrollLeft.value
if (Math.abs(actualScroll - lastScrollLeft) > 5) {
//
currentScrollLeft = actualScroll
} else {
//
currentScrollLeft += AUTO_SCROLL_SPEED
scrollLeft.value = currentScrollLeft
lastScrollLeft = currentScrollLeft
//
const remainingScroll = totalWidth.value - autoScrollPos - props.screenWidth
if (remainingScroll < Math.max(totalWidth.value / 2, props.screenWidth)) {
if (!isLoadingMore && !appendFailed && !isInitialLoading && props.useMockData) {
appendMore()
}
//
const remainingScroll = totalWidth.value - currentScrollLeft - props.screenWidth
if (remainingScroll < Math.max(totalWidth.value / 2, props.screenWidth)) {
// appendMore
// has_more
if (!isLoadingMore && !appendFailed && !isInitialLoading && props.useMockData) {
appendMore()
}
}
} else {
//
lastScrollLeft = scrollLeft.value
currentScrollLeft = lastScrollLeft
}
rafId = rafFn(step)
}
rafId = rafFn(step)
}, 16)
}
const stopAutoScroll = () => {
@ -175,21 +147,41 @@ const stopAutoScroll = () => {
cafFn(rafId)
rafId = null
}
clearInterval(scrollUpdateTimer)
scrollUpdateTimer = null
clearTimeout(appendTimer)
appendTimer = null
clearTimeout(resumeTimer)
resumeTimer = null
clearTimeout(momentumTimer)
momentumTimer = null
userInteracting = false
isLoadingMore = false
}
const pauseForUser = () => {
userInteracting = true
clearTimeout(resumeTimer)
resumeTimer = setTimeout(() => { userInteracting = false }, AUTO_RESUME_DELAY)
// iOS
let lastTouchEndPos = 0 // touchend
const detectMomentumEnd = () => {
clearTimeout(momentumTimer)
lastTouchEndPos = currentScrollLeft
const tick = () => {
momentumTimer = setTimeout(() => {
// lastTouchEndPostouchend
if (Math.abs(currentScrollLeft - lastTouchEndPos) < 3) {
autoScrollPos = currentScrollLeft
startAutoScroll()
} else {
//
lastTouchEndPos = currentScrollLeft
tick()
}
}, 60)
}
tick()
}
// 500ms
//
const scheduleAppend = () => {
if (!isComponentMounted || appendFailed) return
if (appendTimer) clearTimeout(appendTimer)
@ -202,16 +194,23 @@ const scheduleAppend = () => {
}
// ========== / ==========
const onTouchStart = () => pauseForUser()
const onTouchEnd = () => {}
const onTouchStart = () => {
userInteracting = true
clearTimeout(momentumTimer)
clearInterval(scrollUpdateTimer)
}
const onTouchEnd = () => {
// iOS
detectMomentumEnd()
}
const onScroll = (e) => {
if (!isComponentMounted) return
currentScrollLeft = e.detail.scrollLeft
//
const remainingScroll = totalWidth.value - currentScrollLeft - props.screenWidth
if (remainingScroll < Math.max(totalWidth.value / 2, props.screenWidth)) {
// has_more
if (!isLoadingMore && !appendFailed && !isInitialLoading && props.useMockData) {
scheduleAppend()
}
@ -681,12 +680,16 @@ onMounted(() => {
const handleVisibilityChange = () => {
if (!isComponentMounted) return
if (document.hidden) {
userInteracting = true
stopAutoScroll()
} else {
userInteracting = false
if (!rafId) {
startAutoScroll()
}
//
stopAutoScroll()
setTimeout(() => {
if (isComponentMounted) {
autoScrollPos = currentScrollLeft
startAutoScroll()
}
}, 150)
}
}
@ -698,12 +701,15 @@ if (typeof document !== 'undefined') {
watch(() => props.isActive, (active) => {
if (!isComponentMounted) return
if (active) {
userInteracting = false
if (!rafId) {
startAutoScroll()
}
stopAutoScroll()
setTimeout(() => {
if (isComponentMounted) {
autoScrollPos = currentScrollLeft
startAutoScroll()
}
}, 150)
} else {
userInteracting = true
stopAutoScroll()
}
}, { immediate: false })
@ -712,6 +718,7 @@ onUnmounted(() => {
stopAutoScroll()
clearTimeout(resumeTimer)
clearTimeout(appendTimer)
clearTimeout(momentumTimer)
if (typeof document !== 'undefined') {
document.removeEventListener('visibilitychange', handleVisibilityChange)
}