Spaces:
Running
Running
| document.addEventListener('DOMContentLoaded', function() { | |
| // Enhanced parallax effect | |
| const parallaxLayers = document.querySelectorAll('.parallax-layer'); | |
| let ticking = false; | |
| let lastScrollY = 0; | |
| function updateParallax() { | |
| const scrollY = window.pageYOffset; | |
| const windowHeight = window.innerHeight; | |
| const documentHeight = document.body.scrollHeight; | |
| parallaxLayers.forEach(layer => { | |
| const depth = parseFloat(layer.getAttribute('data-depth')); | |
| const layerOffset = layer.getBoundingClientRect().top; | |
| const layerHeight = layer.offsetHeight; | |
| // Calculate position in viewport (0-1) | |
| const viewportPosition = (layerOffset + layerHeight) / (windowHeight + layerHeight); | |
| // Enhanced movement calculation with easing | |
| const movement = -(scrollY * depth * (0.5 + viewportPosition * 0.5)); | |
| // Apply transform with hardware acceleration | |
| layer.style.transform = `translate3d(0, ${movement}px, 0)`; | |
| // Optional: Add perspective for more depth | |
| layer.style.perspective = '1000px'; | |
| layer.style.backfaceVisibility = 'hidden'; | |
| }); | |
| ticking = false; | |
| } | |
| function onScroll() { | |
| lastScrollY = window.scrollY; | |
| if (!ticking) { | |
| window.requestAnimationFrame(updateParallax); | |
| ticking = true; | |
| } | |
| } | |
| window.addEventListener('scroll', onScroll, { passive: true }); | |
| window.addEventListener('resize', updateParallax); | |
| // Initial call | |
| updateParallax(); | |
| // Enhanced horizontal scroll for testimonials with momentum | |
| function setupHorizontalScroll() { | |
| const track = document.querySelector('.testimonial-track'); | |
| if (!track) return; | |
| let isDown = false; | |
| let startX; | |
| let scrollLeft; | |
| let velocity = 0; | |
| let animationFrame; | |
| let lastTime = 0; | |
| track.addEventListener('mousedown', (e) => { | |
| isDown = true; | |
| startX = e.pageX - track.offsetLeft; | |
| scrollLeft = track.scrollLeft; | |
| cancelAnimationFrame(animationFrame); | |
| }); | |
| track.addEventListener('mouseleave', () => { | |
| isDown = false; | |
| applyMomentum(); | |
| }); | |
| track.addEventListener('mouseup', () => { | |
| isDown = false; | |
| applyMomentum(); | |
| }); | |
| track.addEventListener('mousemove', (e) => { | |
| if(!isDown) return; | |
| e.preventDefault(); | |
| const x = e.pageX - track.offsetLeft; | |
| const walk = (x - startX) * 3; // faster scroll | |
| track.scrollLeft = scrollLeft - walk; | |
| velocity = walk - (scrollLeft - track.scrollLeft); | |
| }); | |
| function applyMomentum() { | |
| if (Math.abs(velocity) > 1) { | |
| track.scrollLeft += velocity; | |
| velocity *= 0.95; // friction | |
| animationFrame = requestAnimationFrame(applyMomentum); | |
| } | |
| } | |
| // Touch support | |
| track.addEventListener('touchstart', (e) => { | |
| isDown = true; | |
| startX = e.touches[0].pageX - track.offsetLeft; | |
| scrollLeft = track.scrollLeft; | |
| cancelAnimationFrame(animationFrame); | |
| }); | |
| track.addEventListener('touchend', () => { | |
| isDown = false; | |
| applyMomentum(); | |
| }); | |
| track.addEventListener('touchmove', (e) => { | |
| if(!isDown) return; | |
| const x = e.touches[0].pageX - track.offsetLeft; | |
| const walk = (x - startX) * 3; | |
| track.scrollLeft = scrollLeft - walk; | |
| velocity = walk - (scrollLeft - track.scrollLeft); | |
| }); | |
| } | |
| setupHorizontalScroll(); | |
| // Animation on scroll | |
| const animateOnScroll = function() { | |
| const elements = document.querySelectorAll('.service-card, .testimonial-card'); | |
| elements.forEach(element => { | |
| const elementPosition = element.getBoundingClientRect().top; | |
| const windowHeight = window.innerHeight; | |
| if (elementPosition < windowHeight - 100) { | |
| element.classList.add('animate-fadeInUp'); | |
| } | |
| }); | |
| }; | |
| window.addEventListener('scroll', animateOnScroll); | |
| animateOnScroll(); | |
| // Smooth scroll for anchor links | |
| document.querySelectorAll('a[href^="#"]').forEach(anchor => { | |
| anchor.addEventListener('click', function (e) { | |
| e.preventDefault(); | |
| const targetId = this.getAttribute('href'); | |
| if (targetId === '#') return; | |
| const targetElement = document.querySelector(targetId); | |
| if (targetElement) { | |
| targetElement.scrollIntoView({ | |
| behavior: 'smooth', | |
| block: 'start' | |
| }); | |
| } | |
| }); | |
| }); | |
| // Animation on scroll | |
| const animateOnScroll = function() { | |
| const elements = document.querySelectorAll('.service-card, .testimonial-card'); | |
| elements.forEach(element => { | |
| const elementPosition = element.getBoundingClientRect().top; | |
| const windowHeight = window.innerHeight; | |
| if (elementPosition < windowHeight - 100) { | |
| element.classList.add('animate-fadeInUp'); | |
| } | |
| }); | |
| }; | |
| window.addEventListener('scroll', animateOnScroll); | |
| animateOnScroll(); // Initial check | |
| }); |