File size: 5,237 Bytes
1b72d7e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
import { useCallback, useEffect, useRef, useState } from 'react'
import Logo from './Logo'
import throttle from 'lodash.throttle'
import RandomPostButton from './RandomPostButton'
import SearchButton from './SearchButton'
import DarkModeButton from './DarkModeButton'
import SlideOver from './SlideOver'
import ReadingProgress from './ReadingProgress'
import { MenuListTop } from './MenuListTop'
import { isBrowser } from '@/lib/utils'
import { siteConfig } from '@/lib/config'

/**
 * 顶部导航
 * @param {*} param0
 * @returns
 */
const NavBar = props => {
  const [fixedNav, setFixedNav] = useState(false)
  const [textWhite, setTextWhite] = useState(false)
  const [navBgWhite, setBgWhite] = useState(false)

  const [activeIndex, setActiveIndex] = useState(0)

  const slideOverRef = useRef()

  const toggleMenuOpen = () => {
    slideOverRef?.current?.toggleSlideOvers()
  }

  /**
       * 根据滚动条,切换导航栏样式
       */
  const scrollTrigger = useCallback(throttle(() => {
    const scrollS = window.scrollY
    // 导航栏设置 白色背景
    if (scrollS <= 0) {
      setFixedNav(false)
      setBgWhite(false)

      // 文章详情页特殊处理
      if (document.querySelector('#post-bg')) {
        setFixedNav(true)
        setTextWhite(true)
        setBgWhite(false)
      }
    } else {
      // 向下滚动后的导航样式
      setFixedNav(true)
      setTextWhite(false)
      setBgWhite(true)
    }
  }, 200))

  // 监听滚动
  useEffect(() => {
    scrollTrigger()
    window.addEventListener('scroll', scrollTrigger)
    return () => {
      window.removeEventListener('scroll', scrollTrigger)
    }
  }, [])

  // 监听导航栏显示文字
  useEffect(() => {
    let prevScrollY = 0
    let ticking = false

    const handleScroll = () => {
      if (!ticking) {
        window.requestAnimationFrame(() => {
          const currentScrollY = window.scrollY

          if (currentScrollY > prevScrollY) {
            setActiveIndex(1) // 向下滚动时设置activeIndex为1
          } else {
            setActiveIndex(0) // 向上滚动时设置activeIndex为0
          }

          prevScrollY = currentScrollY
          ticking = false
        })

        ticking = true
      }
    }

    if (isBrowser) {
      window.addEventListener('scroll', handleScroll)
    }

    return () => {
      if (isBrowser) {
        window.removeEventListener('scroll', handleScroll)
      }
    }
  }, [])

  return (<>
        <style jsx>{`
            @keyframes fade-in-down {
                0% {
                opacity: 0.5;
                transform: translateY(-30%);
                }
                100% {
                opacity: 1;
                transform: translateY(0);
                }
            }
            
            @keyframes fade-in-up {
                0% {
                opacity: 0.5;
                transform: translateY(30%);
                }
                100% {
                opacity: 1;
                transform: translateY(0);
                }
            }
            
            .fade-in-down {
                animation: fade-in-down 0.3s ease-in-out;
            }
            
            .fade-in-up {
                animation: fade-in-up 0.3s ease-in-out;
            }
        `}</style>

        {/* 顶部导航菜单栏 */}
        <nav id='nav' className={`z-20 h-16 top-0 w-full
            ${fixedNav ? 'fixed' : 'relative bg-transparent'} 
            ${textWhite ? 'text-white ' : 'text-black dark:text-white'}  
            ${navBgWhite ? 'bg-white dark:bg-[#18171d]' : 'bg-transparent'}`}>

            <div className='flex h-full mx-auto justify-between items-center max-w-[86rem] px-8'>
                {/* 左侧logo */}
                <div className='flex'>
                    <Logo {...props} />
                </div>

                {/* 中间菜单 */}
                <div id='nav-bar-swipe' className={`hidden lg:flex flex-grow flex-col items-center justify-center h-full relative w-full ${activeIndex === 0 ? 'fade-in-down' : 'fade-in-up'}`}>
                    {activeIndex === 0 && <MenuListTop {...props} />}
                    {activeIndex === 1 && <h1 className='font-bold text-center text-light-400 dark:text-gray-400'>{siteConfig('AUTHOR') || siteConfig('TITLE')} {siteConfig('BIO') && <>|</>} {siteConfig('BIO')}</h1>}
                </div>

                {/* 右侧固定 */}
                <div className='flex flex-shrink-0 justify-center items-center'>
                    <RandomPostButton {...props} />
                    <SearchButton {...props}/>
                    {!JSON.parse(siteConfig('THEME_SWITCH')) && <div className='hidden md:block'><DarkModeButton {...props} /></div>}
                    <ReadingProgress />

                    {/* 移动端菜单按钮 */}
                    <div onClick={toggleMenuOpen} className='flex lg:hidden w-8 justify-center items-center h-8 cursor-pointer'>
                        <i className='fas fa-bars' />
                    </div>
                </div>

                {/* 右边侧拉抽屉 */}
                <SlideOver cRef={slideOverRef} {...props} />
            </div>
        </nav>
    </>)
}

export default NavBar