Created
May 14, 2025 02:51
-
-
Save Notookk/70682722432d1f2231e37d98e1dc944b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // DOM Content Loaded | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // Set current year in footer | |
| document.getElementById('year').textContent = new Date().getFullYear(); | |
| // Initialize particles only on desktop | |
| if (window.innerWidth > 768) { | |
| createParticles(); | |
| } | |
| // Start typing animation | |
| setTimeout(typeText, 1500); | |
| }); | |
| // Sticky header | |
| window.onscroll = () => { | |
| let header = document.querySelector("header"); | |
| header.classList.toggle("sticky", window.scrollY > 100); | |
| }; | |
| // Mobile menu toggle | |
| document.querySelector("#menu-icon").onclick = () => { | |
| let navbar = document.querySelector(".navbar"); | |
| navbar.classList.toggle("active"); | |
| }; | |
| // Close menu when clicking on a nav link | |
| document.querySelectorAll(".navbar a").forEach((link) => { | |
| link.addEventListener("click", () => { | |
| document.querySelector(".navbar").classList.remove("active"); | |
| }); | |
| }); | |
| // Theme toggle functionality | |
| const themeToggle = document.getElementById('theme-toggle'); | |
| themeToggle.addEventListener('click', () => { | |
| document.documentElement.toggleAttribute('data-theme'); | |
| localStorage.setItem('theme', | |
| document.documentElement.hasAttribute('data-theme') ? 'light' : 'dark'); | |
| }); | |
| // Check for saved theme preference | |
| if (localStorage.getItem('theme') === 'light') { | |
| document.documentElement.setAttribute('data-theme', 'light'); | |
| } | |
| // Create particles | |
| function createParticles() { | |
| const container = document.querySelector(".particle-container"); | |
| const colors = ["#917fb3", "#e5beec", "#fde2f3"]; | |
| for (let i = 0; i < 50; i++) { | |
| const particle = document.createElement("div"); | |
| particle.classList.add("particle"); | |
| // Random position | |
| const posX = Math.random() * window.innerWidth; | |
| const posY = Math.random() * window.innerHeight; | |
| // Random size | |
| const size = Math.random() * 5 + 1; | |
| // Random color | |
| const color = colors[Math.floor(Math.random() * colors.length)]; | |
| // Random animation delay | |
| const delay = Math.random() * 5; | |
| // Random animation duration | |
| const duration = Math.random() * 5 + 5; | |
| // Apply styles | |
| particle.style.left = `${posX}px`; | |
| particle.style.top = `${posY}px`; | |
| particle.style.width = `${size}px`; | |
| particle.style.height = `${size}px`; | |
| particle.style.backgroundColor = color; | |
| particle.style.animationDelay = `${delay}s`; | |
| particle.style.animationDuration = `${duration}s`; | |
| container.appendChild(particle); | |
| } | |
| } | |
| // Typing animation for the subtitle | |
| const textAnimate = document.querySelector(".text-animate h3"); | |
| const text = textAnimate.textContent; | |
| textAnimate.textContent = ""; | |
| let charIndex = 0; | |
| function typeText() { | |
| if (charIndex < text.length) { | |
| textAnimate.textContent += text.charAt(charIndex); | |
| charIndex++; | |
| setTimeout(typeText, 100); | |
| } else { | |
| setTimeout(eraseText, 2000); | |
| } | |
| } | |
| function eraseText() { | |
| if (charIndex > 0) { | |
| textAnimate.textContent = text.substring(0, charIndex - 1); | |
| charIndex--; | |
| setTimeout(eraseText, 50); | |
| } else { | |
| setTimeout(typeText, 1000); | |
| } | |
| } | |
| // Smooth scrolling for anchor links | |
| document.querySelectorAll('a[href^="#"]').forEach((anchor) => { | |
| anchor.addEventListener("click", function(e) { | |
| e.preventDefault(); | |
| const targetId = this.getAttribute("href"); | |
| const targetElement = document.querySelector(targetId); | |
| if (targetElement) { | |
| window.scrollTo({ | |
| top: targetElement.offsetTop - 100, | |
| behavior: "smooth" | |
| }); | |
| } | |
| }); | |
| }); | |
| // Form submission handling | |
| const form = document.getElementById('contact-form'); | |
| const formStatus = document.getElementById('form-status'); | |
| if (form) { | |
| form.addEventListener('submit', async (e) => { | |
| e.preventDefault(); | |
| formStatus.textContent = "Sending..."; | |
| try { | |
| const response = await fetch(form.action, { | |
| method: 'POST', | |
| body: new FormData(form), | |
| headers: { 'Accept': 'application/json' } | |
| }); | |
| if (response.ok) { | |
| formStatus.textContent = "Thanks for your message! I'll get back to you soon."; | |
| form.reset(); | |
| } else { | |
| throw new Error('Form submission failed'); | |
| } | |
| } catch (error) { | |
| formStatus.textContent = "Oops! Something went wrong. Please try again later."; | |
| console.error('Error:', error); | |
| } | |
| }); | |
| } | |
| // Intersection Observer for animations | |
| const observer = new IntersectionObserver((entries) => { | |
| entries.forEach((entry) => { | |
| if (entry.isIntersecting) { | |
| entry.target.classList.add("show"); | |
| } | |
| }); | |
| }, { threshold: 0.3 }); | |
| // Observe all sections and animate-on-scroll elements | |
| document.querySelectorAll("section, .animate-on-scroll").forEach((element) => { | |
| observer.observe(element); | |
| }); | |
| // 3D tilt effect for project cards (optional) | |
| const projectsBoxes = document.querySelectorAll('.projects-box'); | |
| projectsBoxes.forEach(box => { | |
| box.addEventListener('mousemove', (e) => { | |
| const xAxis = (window.innerWidth / 2 - e.pageX) / 10; | |
| const yAxis = (window.innerHeight / 2 - e.pageY) / 10; | |
| box.style.transform = `rotateY(${xAxis}deg) rotateX(${yAxis}deg)`; | |
| }); | |
| box.addEventListener('mouseleave', () => { | |
| box.style.transform = 'rotateY(0) rotateX(0)'; | |
| }); | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment