diff options
Diffstat (limited to 'static/script.js')
-rw-r--r-- | static/script.js | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/static/script.js b/static/script.js new file mode 100644 index 0000000..e1fd02c --- /dev/null +++ b/static/script.js @@ -0,0 +1,157 @@ +// Smooth scrolling for navigation links +document.querySelectorAll('a[href^="#"]').forEach(anchor => { + anchor.addEventListener('click', function (e) { + e.preventDefault(); + const target = document.querySelector(this.getAttribute('href')); + if (target) { + target.scrollIntoView({ + behavior: 'smooth', + block: 'start' + }); + } + }); +}); + +// Mobile menu toggle +const hamburger = document.querySelector('.hamburger'); +const navMenu = document.querySelector('.nav-menu'); + +hamburger.addEventListener('click', () => { + hamburger.classList.toggle('active'); + navMenu.classList.toggle('active'); +}); + +// Close mobile menu when clicking on a link +document.querySelectorAll('.nav-link').forEach(n => n.addEventListener('click', () => { + hamburger.classList.remove('active'); + navMenu.classList.remove('active'); +})); + +// Navbar background on scroll +window.addEventListener('scroll', () => { + const navbar = document.querySelector('.navbar'); + if (window.scrollY > 50) { + navbar.style.background = 'rgba(255, 255, 255, 0.98)'; + } else { + navbar.style.background = 'rgba(255, 255, 255, 0.95)'; + } +}); + +// Intersection Observer for animations +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); + +// Observe elements for animation +document.querySelectorAll('.project-card, .stat, .about-text').forEach(el => { + el.style.opacity = '0'; + el.style.transform = 'translateY(30px)'; + el.style.transition = 'opacity 0.6s ease, transform 0.6s ease'; + observer.observe(el); +}); + +// Form submission +document.querySelector('.contact-form').addEventListener('submit', function(e) { + e.preventDefault(); + + // Get form data + const formData = new FormData(this); + const name = this.querySelector('input[type="text"]').value; + const email = this.querySelector('input[type="email"]').value; + const message = this.querySelector('textarea').value; + + // Simple validation + if (!name || !email || !message) { + alert('Please fill in all fields'); + return; + } + + // Simulate form submission + const submitBtn = this.querySelector('button[type="submit"]'); + const originalText = submitBtn.textContent; + + submitBtn.textContent = 'Sending...'; + submitBtn.disabled = true; + + setTimeout(() => { + alert('Thank you for your message! I\'ll get back to you soon.'); + this.reset(); + submitBtn.textContent = originalText; + submitBtn.disabled = false; + }, 2000); +}); + +// Add typing animation to hero title +const heroTitle = document.querySelector('.hero-title'); +if (heroTitle) { + const text = heroTitle.innerHTML; + heroTitle.innerHTML = ''; + + let i = 0; + const typeWriter = () => { + if (i < text.length) { + heroTitle.innerHTML += text.charAt(i); + i++; + setTimeout(typeWriter, 50); + } + }; + + // Start typing animation after page load + window.addEventListener('load', () => { + setTimeout(typeWriter, 500); + }); +} + +// Parallax effect for floating cards +window.addEventListener('scroll', () => { + const scrolled = window.pageYOffset; + const parallaxElements = document.querySelectorAll('.floating-card'); + + parallaxElements.forEach((element, index) => { + const speed = 0.5 + (index * 0.1); + const yPos = -(scrolled * speed); + element.style.transform = `translateY(${yPos}px)`; + }); +}); + +// Add mobile menu styles dynamically +const style = document.createElement('style'); +style.textContent = ` + @media (max-width: 768px) { + .nav-menu.active { + display: flex; + position: absolute; + top: 100%; + left: 0; + width: 100%; + background: white; + flex-direction: column; + padding: 1rem 2rem; + box-shadow: var(--shadow); + border-top: 1px solid var(--border); + } + + .hamburger.active span:nth-child(1) { + transform: rotate(-45deg) translate(-5px, 6px); + } + + .hamburger.active span:nth-child(2) { + opacity: 0; + } + + .hamburger.active span:nth-child(3) { + transform: rotate(45deg) translate(-5px, -6px); + } + } +`; +document.head.appendChild(style); |