diff --git a/main.js b/main.js new file mode 100644 index 0000000..c3a8b9e --- /dev/null +++ b/main.js @@ -0,0 +1,149 @@ +// ======================================== +// 导航栏滚动效果 +// ======================================== +const navbar = document.getElementById('navbar'); +let lastScroll = 0; + +window.addEventListener('scroll', () => { + const currentScroll = window.pageYOffset; + + // 添加滚动时的阴影效果 + if (currentScroll > 50) { + navbar.style.boxShadow = '0 4px 20px rgba(0, 0, 0, 0.1)'; + } else { + navbar.style.boxShadow = '0 2px 10px rgba(0, 0, 0, 0.05)'; + } + + lastScroll = currentScroll; +}); + +// ======================================== +// 移动端汉堡菜单 +// ======================================== +const hamburger = document.getElementById('hamburger'); +const navMenu = document.getElementById('navMenu'); +const navLinks = document.querySelectorAll('.nav-link'); + +hamburger.addEventListener('click', () => { + hamburger.classList.toggle('active'); + navMenu.classList.toggle('active'); +}); + +// 点击导航链接后关闭菜单 +navLinks.forEach(link => { + link.addEventListener('click', () => { + hamburger.classList.remove('active'); + navMenu.classList.remove('active'); + }); +}); + +// ======================================== +// 平滑滚动到锚点 +// ======================================== +document.querySelectorAll('a[href^="#"]').forEach(anchor => { + anchor.addEventListener('click', function (e) { + e.preventDefault(); + const target = document.querySelector(this.getAttribute('href')); + + if (target) { + const offsetTop = target.offsetTop - 80; // 减去导航栏高度 + + window.scrollTo({ + top: offsetTop, + behavior: 'smooth' + }); + } + }); +}); + +// ======================================== +// 滚动时导航链接高亮 +// ======================================== +const sections = document.querySelectorAll('section[id]'); + +function highlightNavigation() { + const scrollY = window.pageYOffset; + + sections.forEach(section => { + const sectionHeight = section.offsetHeight; + const sectionTop = section.offsetTop - 100; + const sectionId = section.getAttribute('id'); + const navLink = document.querySelector(`.nav-link[href="#${sectionId}"]`); + + if (navLink) { + if (scrollY > sectionTop && scrollY <= sectionTop + sectionHeight) { + navLink.classList.add('active'); + } else { + navLink.classList.remove('active'); + } + } + }); +} + +window.addEventListener('scroll', highlightNavigation); + +// ======================================== +// 卡片进入视口时的动画效果 +// ======================================== +const observerOptions = { + threshold: 0.1, + rootMargin: '0px 0px -50px 0px' +}; + +const observer = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + entry.target.style.opacity = '1'; + entry.target.style.transform = 'translateY(0)'; + } + }); +}, observerOptions); + +// 观察所有卡片元素 +document.querySelectorAll('.card').forEach(card => { + card.style.opacity = '0'; + card.style.transform = 'translateY(30px)'; + card.style.transition = 'opacity 0.6s ease-out, transform 0.6s ease-out'; + observer.observe(card); +}); + +// ======================================== +// 页面加载完成后的初始化 +// ======================================== +window.addEventListener('load', () => { + // 添加页面加载完成的类,用于触发初始动画 + document.body.classList.add('loaded'); + + // 立即执行一次高亮检查 + highlightNavigation(); +}); + +// ======================================== +// 图片懒加载(可选优化) +// ======================================== +if ('IntersectionObserver' in window) { + const imageObserver = new IntersectionObserver((entries, observer) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + const img = entry.target; + if (img.dataset.src) { + img.src = img.dataset.src; + img.removeAttribute('data-src'); + observer.unobserve(img); + } + } + }); + }); + + // 可以将来为实际图片添加 data-src 属性实现懒加载 +} + +// ======================================== +// 响应式处理 - 窗口大小改变时重置菜单 +// ======================================== +window.addEventListener('resize', () => { + if (window.innerWidth > 768) { + hamburger.classList.remove('active'); + navMenu.classList.remove('active'); + } +});