fix: correct RightFloatArea hiding behavior when scrolling back to top

This commit is contained in:
LooseLi
2025-04-15 14:45:58 +08:00
parent 6f770a5165
commit f6c2ccf0cc

View File

@@ -1,36 +1,52 @@
import throttle from 'lodash.throttle'
import { useCallback, useEffect, useState } from 'react'
import ButtonDarkModeFloat from './ButtonFloatDarkMode'
import ButtonJumpToTop from './ButtonJumpToTop'
/**
* 悬浮在右下角的按钮当页面向下滚动100px时会出现
* 当页面回到顶部时会隐藏
* @param {*} param0
* @returns
*/
export default function RightFloatArea({ floatSlot }) {
const [showFloatButton, switchShow] = useState(false)
const scrollListener = useCallback(
throttle(() => {
const targetRef = document.getElementById('wrapper')
const clientHeight = targetRef?.clientHeight
const scrollY = window.pageYOffset
const fullHeight = clientHeight - window.outerHeight
let per = parseFloat(((scrollY / fullHeight) * 100).toFixed(0))
if (per > 100) per = 100
const shouldShow = scrollY > 100 && per > 0
// 右下角显示悬浮按钮
if (shouldShow !== showFloatButton) {
switchShow(shouldShow)
}
}, 200)
)
const scrollListener = useCallback(() => {
const targetRef = document.getElementById('wrapper') || document.documentElement
const clientHeight = targetRef?.clientHeight || 0
const scrollY = window.pageYOffset || document.documentElement.scrollTop || 0
const viewportHeight = window.innerHeight || document.documentElement.clientHeight || 0
const fullHeight = Math.max(1, clientHeight - viewportHeight)
let per = parseFloat(((scrollY / fullHeight) * 100).toFixed(0))
// 完整的边界处理
if (isNaN(per) || per < 0) per = 0
if (per > 100) per = 100
const shouldShow = scrollY > 100 && per > 0
// 右下角显示悬浮按钮
if (shouldShow !== showFloatButton) {
switchShow(shouldShow)
}
}, [showFloatButton])
useEffect(() => {
document.addEventListener('scroll', scrollListener)
return () => document.removeEventListener('scroll', scrollListener)
}, [])
const throttledScroll = () => {
window.requestAnimationFrame(() => {
scrollListener()
})
}
window.addEventListener('scroll', throttledScroll)
// 初始调用一次检查初始状态
scrollListener()
return () => window.removeEventListener('scroll', throttledScroll)
}, [scrollListener])
return (
<div
@@ -39,7 +55,7 @@ export default function RightFloatArea({ floatSlot }) {
' duration-300 transition-all bottom-12 right-1 fixed justify-end z-20 text-white bg-indigo-500 dark:bg-hexo-black-gray rounded-sm'
}>
<div
className={'justify-center flex flex-col items-center cursor-pointer'}>
className={'justify-center flex flex-col items-center cursor-pointer'}>
<ButtonDarkModeFloat />
{floatSlot}
<ButtonJumpToTop />