first commit
This commit is contained in:
148
src/components/Navigation.js
Normal file
148
src/components/Navigation.js
Normal file
@@ -0,0 +1,148 @@
|
||||
import React, { useState } from 'react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
|
||||
const Navigation = ({ currentSection, sections, onSectionChange }) => {
|
||||
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
||||
|
||||
const menuItems = [
|
||||
{ name: '发现', engName: 'Discover', sectionIndex: 0 },
|
||||
{ name: '产品', engName: 'Products', sectionIndex: 1 },
|
||||
{ name: '团队', engName: 'Team', sectionIndex: 2 },
|
||||
{ name: '案例', engName: 'Cases', sectionIndex: 3 },
|
||||
{ name: '联系', engName: 'Contact', sectionIndex: 4 }
|
||||
];
|
||||
|
||||
const handleItemClick = (sectionIndex) => {
|
||||
onSectionChange(sectionIndex);
|
||||
setIsMobileMenuOpen(false);
|
||||
};
|
||||
|
||||
const toggleMobileMenu = () => {
|
||||
setIsMobileMenuOpen(!isMobileMenuOpen);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<motion.nav
|
||||
className="navigation-glass"
|
||||
initial={{ y: -50, opacity: 0 }}
|
||||
animate={{ y: 0, opacity: 1 }}
|
||||
transition={{ duration: 0.8, delay: 0.2 }}
|
||||
>
|
||||
{/* Logo */}
|
||||
<motion.div
|
||||
className="logo-glass"
|
||||
whileHover={{
|
||||
scale: 1.02,
|
||||
y: -1
|
||||
}}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
onClick={() => handleItemClick(0)}
|
||||
>
|
||||
<motion.div
|
||||
className="logo-icon-glass"
|
||||
whileHover={{
|
||||
rotate: [0, -5, 5, 0],
|
||||
scale: 1.1
|
||||
}}
|
||||
transition={{ duration: 0.5 }}
|
||||
>
|
||||
Q
|
||||
</motion.div>
|
||||
<motion.span
|
||||
className="logo-text"
|
||||
>
|
||||
Quant Speed
|
||||
</motion.span>
|
||||
</motion.div>
|
||||
|
||||
{/* 桌面端菜单 */}
|
||||
<div className="nav-menu-glass">
|
||||
{menuItems.map((item, index) => (
|
||||
<motion.div
|
||||
key={index}
|
||||
className={`nav-item-glass ${currentSection === item.sectionIndex ? 'active' : ''}`}
|
||||
whileHover={{
|
||||
scale: 1.05,
|
||||
y: -2
|
||||
}}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
onClick={() => handleItemClick(item.sectionIndex)}
|
||||
>
|
||||
<span className="nav-item-main">{item.name}</span>
|
||||
<span className="nav-item-sub">{item.engName}</span>
|
||||
{currentSection === item.sectionIndex && (
|
||||
<motion.div
|
||||
className="nav-item-indicator"
|
||||
layoutId="activeIndicator"
|
||||
initial={false}
|
||||
transition={{ type: "spring", stiffness: 300, damping: 30 }}
|
||||
/>
|
||||
)}
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* 移动端汉堡菜单按钮 */}
|
||||
<motion.div
|
||||
className={`hamburger-glass ${isMobileMenuOpen ? 'active' : ''}`}
|
||||
whileHover={{ scale: 1.1 }}
|
||||
whileTap={{ scale: 0.9 }}
|
||||
onClick={toggleMobileMenu}
|
||||
>
|
||||
<motion.div
|
||||
className="hamburger-line"
|
||||
animate={isMobileMenuOpen ? { rotate: 45, y: 6 } : { rotate: 0, y: 0 }}
|
||||
/>
|
||||
<motion.div
|
||||
className="hamburger-line"
|
||||
animate={isMobileMenuOpen ? { opacity: 0 } : { opacity: 1 }}
|
||||
/>
|
||||
<motion.div
|
||||
className="hamburger-line"
|
||||
animate={isMobileMenuOpen ? { rotate: -45, y: -6 } : { rotate: 0, y: 0 }}
|
||||
/>
|
||||
</motion.div>
|
||||
</motion.nav>
|
||||
|
||||
{/* 移动端菜单 */}
|
||||
<AnimatePresence>
|
||||
{isMobileMenuOpen && (
|
||||
<motion.div
|
||||
className="mobile-menu-glass"
|
||||
initial={{ opacity: 0, y: -20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -20 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
>
|
||||
<motion.div
|
||||
className="mobile-menu-content"
|
||||
initial={{ scale: 0.95 }}
|
||||
animate={{ scale: 1 }}
|
||||
exit={{ scale: 0.95 }}
|
||||
>
|
||||
{menuItems.map((item, index) => (
|
||||
<motion.div
|
||||
key={index}
|
||||
className={`mobile-nav-item ${currentSection === item.sectionIndex ? 'active' : ''}`}
|
||||
whileHover={{ x: 10 }}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
onClick={() => handleItemClick(item.sectionIndex)}
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: index * 0.1 }}
|
||||
>
|
||||
<span className="mobile-nav-main">{item.name}</span>
|
||||
<span className="mobile-nav-sub">{item.engName}</span>
|
||||
</motion.div>
|
||||
))}
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Navigation;
|
||||
Reference in New Issue
Block a user