mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-15 15:09:25 +00:00
69 lines
2.0 KiB
JavaScript
69 lines
2.0 KiB
JavaScript
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(() => {
|
||
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(() => {
|
||
const throttledScroll = () => {
|
||
window.requestAnimationFrame(() => {
|
||
scrollListener()
|
||
})
|
||
}
|
||
|
||
window.addEventListener('scroll', throttledScroll)
|
||
|
||
// 初始调用一次检查初始状态
|
||
scrollListener()
|
||
|
||
return () => window.removeEventListener('scroll', throttledScroll)
|
||
}, [scrollListener])
|
||
|
||
return (
|
||
<div
|
||
className={
|
||
(showFloatButton ? 'opacity-100 ' : 'invisible opacity-0') +
|
||
' 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'}>
|
||
<ButtonDarkModeFloat />
|
||
{floatSlot}
|
||
<ButtonJumpToTop />
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|