Spaces:
Running
Running
| 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?'); | |
| }); | |
| }); |