记录一次自己反复修改实现的导航栏效果 具体展示会在完工后上线 期间遇到各种bug 最终修复成功 实现了我想要的效果

  1. 在components目录下创建 Navbar.js
'use client';

import Link from 'next/link';

import { useState, useEffect } from 'react';

import { lora } from 'utils/font';

import { cn } from 'utils/misc';

import { Menu, X } from 'lucide-react';

const navFontClass = cn(

  lora.className,

  'text-white hover:text-rose-300 transition duration-300 text-lg'

);

const Navbar = () => {

  const [nav, setNav] = useState(false);

  const [scrollPos, setScrollPos] = useState(0);

  const [hidden, setHidden] = useState(false);

  // 处理滚动事件

  useEffect(() => {

​    const handleScroll = () => {

​      const currentScrollPos = window.pageYOffset || document.documentElement.scrollTop;

​      if (nav) return;

​      if (currentScrollPos > scrollPos + 5) {

​        setHidden(true);

​      } else if (currentScrollPos < scrollPos - 5) {

​        setHidden(false);

​      }

​      setScrollPos(currentScrollPos <= 0 ? 0 : currentScrollPos);

​    };

​    window.addEventListener('scroll', handleScroll);

​    return () => window.removeEventListener('scroll', handleScroll);

  }, [scrollPos, nav]);

  // 处理窗口大小变化

  useEffect(() => {

​    const handleResize = () => {

​      if (window.innerWidth >= 768) {

​        setNav(false); // 切换到桌面端时关闭菜单

​      }

​    };

​    window.addEventListener('resize', handleResize);

​    return () => window.removeEventListener('resize', handleResize);

  }, []);

  const scrollToTop = () => {

​    const scrollDuration = 1000;

​    const scrollStep = -window.scrollY / (scrollDuration / 16);

​    const scrollAnimation = () => {

​      if (window.scrollY !== 0) {

​        window.scrollBy(0, scrollStep);

​        requestAnimationFrame(scrollAnimation);

​      }

​    };

​    requestAnimationFrame(scrollAnimation);

  };

  return (

​    <nav className={`navbar ${hidden ? 'navbar-hidden' : 'navbar-visible'} bg-transparent p-4 w-full z-10`}>

      <div className="flex justify-between items-center w-full">

        <div className={`${navFontClass} font-bold pl-4`}>

​          <Link href="/" onClick={(e) => { e.preventDefault(); scrollToTop(); }}>

​            Dark.Lotus

​          </Link>

​        </div>

​        {/* Desktop Links */}

        <div className="hidden md:flex space-x-8 pr-4">

​          <Link href="https://darklotus.cn" target="_blank" className={navFontClass}>Home</Link>

​          <Link href="https://blog.darklotus.cn" target="_blank" className={navFontClass}>Blog</Link>

​          <Link href="/projects" className={navFontClass}>Docs</Link>

​          <Link href="/contact" className={navFontClass}>About</Link>

​        </div>

​        {/* Mobile Menu Button */}

        <div className="md:hidden pr-4 z-20">

​          <button onClick={() => setNav(!nav)} className={navFontClass}>

​            {nav ? <X size={24} /> : <Menu size={24} />}

​          </button>

​        </div>

​      </div>

​      {/* Mobile Menu Overlay */}

​      {nav && (

        <div className="menu-overlay" onClick={() => setNav(false)}>

          <div className="menu-content" onClick={(e) => e.stopPropagation()}>

​            <Link href="/" onClick={(e) => { e.preventDefault(); scrollToTop(); setNav(false); }} className={`block py-4 text-white ${navFontClass}`}>

​              Home

​            </Link>

​            <Link href="https://blog.darklotus.cn" target="_blank" rel="noopener noreferrer" onClick={() => setNav(false)} className={`block py-4 text-white ${navFontClass}`}>

​              Blog

​            </Link>

​            <Link href="https://docs.darklotus.cn" target="_blank" rel="noopener noreferrer" onClick={() => setNav(false)} className={`block py-4 text-white ${navFontClass}`}>

​              Docs

​            </Link>

​            <Link href="https://about.darklotus.cn" target="_blank" rel="noopener noreferrer" onClick={() => setNav(false)} className={`block py-4 text-white ${navFontClass}`}>

​              About

​            </Link>

​          </div>

​        </div>

​      )}

​    </nav>

  );

};

export default Navbar;
  1. index.tsx 首页引用

    // Import the Navbar component
    import Navbar from 'components/Navbar';
  2. 插入导航栏组件
    ps:以下代码是的摆放位置 不能直接复制粘贴!

    export function Home() {
      return (
     <main className="w-full overflow-hidden">
       {/* Include the Navbar component */}
       <Navbar />

4.全局CSS

/* 手机端导航栏 */

  .navbar {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    transition: transform 0.3s ease-in-out;
  }
  
  .navbar-hidden {
    transform: translateY(-100%);
  }
  
.menu-overlay {
  background-color: rgba(0, 0, 0, 0.8); /* 半透明黑色背景 */
  position: fixed;
  inset: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 10; /* 确保菜单在其他内容之上 */
 

}

.menu-content {
  background-color: transparent; /* 菜单内容的背景色 */
  padding: 2rem; /* 菜单内容的内边距 */
  border-radius: 0.5rem; /* 菜单内容的圆角 */
  text-align: center;
}


/* 导航栏桌面端 */
@media (min-width: 768px) {
  .navbar {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    transition: transform 0.3s ease-in-out;
  }
  
  .navbar-hidden {
    transform: translateY(-100%);
  }
  
  .navbar-visible {
    transform: translateY(0);
  }
}
最后修改:2024 年 09 月 13 日
如果觉得我的文章对你有用,请随意赞赏