document.addEventListener('DOMContentLoaded', function() { // Set up Three.js particle background const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); const renderer = new THREE.WebGLRenderer({ alpha: true }); renderer.setSize(window.innerWidth, window.innerHeight); document.getElementById('particles-bg').appendChild(renderer.domElement); // Create particles const particlesGeometry = new THREE.BufferGeometry(); const particlesCount = 7000; const posArray = new Float32Array(particlesCount * 3); const colorArray = new Float32Array(particlesCount * 3); for (let i = 0; i < particlesCount * 3; i += 3) { // Position posArray[i] = (Math.random() - 0.5) * 150; posArray[i + 1] = (Math.random() - 0.5) * 150; posArray[i + 2] = (Math.random() - 0.5) * 150; // Color colorArray[i] = Math.random() * 0.5 + 0.5; // R: 0.5-1.0 colorArray[i + 1] = Math.random() * 0.3; // G: 0-0.3 colorArray[i + 2] = Math.random() * 0.5 + 0.5; // B: 0.5-1.0 } particlesGeometry.setAttribute('position', new THREE.BufferAttribute(posArray, 3)); particlesGeometry.setAttribute('color', new THREE.BufferAttribute(colorArray, 3)); const particlesMaterial = new THREE.PointsMaterial({ size: 0.15, vertexColors: true, transparent: true, opacity: 0.8, sizeAttenuation: true }); const particlesMesh = new THREE.Points(particlesGeometry, particlesMaterial); scene.add(particlesMesh); camera.position.z = 8; // Mouse movement effect let mouseX = 0; let mouseY = 0; document.addEventListener('mousemove', (event) => { mouseX = (event.clientX / window.innerWidth) * 2 - 1; mouseY = -(event.clientY / window.innerHeight) * 2 + 1; }); // Animation loop function animate() { requestAnimationFrame(animate); // Rotate particles particlesMesh.rotation.x += 0.001; particlesMesh.rotation.y += 0.002; // Move camera based on mouse position camera.position.x += (mouseX * 3 - camera.position.x) * 0.01; camera.position.y += (mouseY * 3 - camera.position.y) * 0.01; camera.lookAt(scene.position); renderer.render(scene, camera); } animate(); // Handle window resize window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }); // GSAP animations for scroll effects gsap.registerPlugin(ScrollTrigger); // Animate sections on scroll gsap.utils.toArray('.feature-card, .portfolio-item, .service-card, .pricing-card').forEach(element => { gsap.from(element, { scrollTrigger: { trigger: element, start: 'top 90%', toggleActions: 'play none none none' }, opacity: 0, y: 70, duration: 1.2, ease: 'power3.out' }); }); // Header scroll effect const header = document.getElementById('header'); window.addEventListener('scroll', () => { if (window.scrollY > 50) { header.classList.add('scrolled'); } else { header.classList.remove('scrolled'); } // Show/hide scroll to top button const scrollTopBtn = document.getElementById('scrollTop'); if (window.scrollY > 500) { scrollTopBtn.classList.add('visible'); } else { scrollTopBtn.classList.remove('visible'); } }); // Scroll to top functionality document.getElementById('scrollTop').addEventListener('click', () => { window.scrollTo({ top: 0, behavior: 'smooth' }); }); // Smooth scrolling for anchor links document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function(e) { e.preventDefault(); const target = document.querySelector(this.getAttribute('href')); if (target) { window.scrollTo({ top: target.offsetTop - 80, behavior: 'smooth' }); } }); }); // Portfolio Filter Functionality const filterButtons = document.querySelectorAll('.filter-btn'); const portfolioItems = document.querySelectorAll('.portfolio-item'); filterButtons.forEach(button => { button.addEventListener('click', () => { // Remove active class from all buttons filterButtons.forEach(btn => btn.classList.remove('active')); // Add active class to clicked button button.classList.add('active'); const filter = button.getAttribute('data-filter'); // Filter portfolio items portfolioItems.forEach(item => { if (filter === 'all' || item.getAttribute('data-category') === filter) { item.style.display = 'block'; gsap.fromTo(item, {opacity: 0, y: 50}, {opacity: 1, y: 0, duration: 0.8, ease: 'power2.out'}); } else { gsap.to(item, {opacity: 0, y: 50, duration: 0.5, ease: 'power2.out', onComplete: () => {item.style.display = 'none';} }); } }); }); }); // Enhanced form validation const contactForm = document.getElementById('contactForm'); contactForm.addEventListener('submit', function(e) { e.preventDefault(); let isValid = true; // Reset all error states const formGroups = this.querySelectorAll('.form-group'); formGroups.forEach(group => { group.classList.remove('error', 'success'); }); // Validate name const nameInput = document.getElementById('name'); if (!nameInput.value.trim()) { nameInput.parentElement.classList.add('error'); isValid = false; } else { nameInput.parentElement.classList.add('success'); } // Validate email const emailInput = document.getElementById('email'); const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(emailInput.value)) { emailInput.parentElement.classList.add('error'); isValid = false; } else { emailInput.parentElement.classList.add('success'); } // Validate message const messageInput = document.getElementById('message'); if (!messageInput.value.trim()) { messageInput.parentElement.classList.add('error'); isValid = false; } else { messageInput.parentElement.classList.add('success'); } if (isValid) { // Form is valid - show success animation gsap.to(contactForm, { opacity: 0, y: -20, duration: 0.5, onComplete: function() { alert('Thank you for your message! We will contact you shortly.'); contactForm.reset(); gsap.to(contactForm, {opacity: 1, y: 0, duration: 0.5}); // Reset success states formGroups.forEach(group => { group.classList.remove('success'); }); } }); } }); // Button functionality document.getElementById('getStartedBtn').addEventListener('click', function() { document.querySelector('contact.html').scrollIntoView({ behavior: 'smooth' }); }); document.getElementById("exploreBtn").addEventListener("click", function() { alert("Exploring solutions..."); window.location.href = "../c1/solutions.html"; }); document.getElementById("portfolioBtn").addEventListener("click", function() { window.location.href = "../portfolio.html"; }); // Chat bubble functionality document.querySelector('.chat-bubble').addEventListener('click', function() { alert('Welcome to FelixioTech! How can we assist you today?'); }); });