/** * Roof Cleaning Drone Background Animations * Creates animated drones with water spray effects */ (function() { document.addEventListener('DOMContentLoaded', function() { // Apply the background to the entire site applyCleanBackground(); // Add animated drones to hero section enhanceHeroSection(); // Add water droplet effects to service cards enhanceServiceCards(); }); function applyCleanBackground() { // Remove any existing star/cosmic backgrounds const existingStars = document.querySelector('.stars'); if (existingStars) { existingStars.remove(); } // Add clean background to body document.body.style.background = '#f8f9fa'; document.body.style.backgroundImage = ` linear-gradient(120deg, rgba(99, 183, 241, 0.1) 0%, transparent 40%), linear-gradient(240deg, rgba(220, 237, 249, 0.2) 0%, transparent 40%) `; // Add subtle diagonal pattern const pattern = document.createElement('div'); pattern.className = 'clean-pattern'; pattern.style.position = 'fixed'; pattern.style.top = '0'; pattern.style.left = '0'; pattern.style.width = '100%'; pattern.style.height = '100%'; pattern.style.pointerEvents = 'none'; pattern.style.opacity = '0.03'; pattern.style.zIndex = '-1'; pattern.style.backgroundImage = ` repeating-linear-gradient( 45deg, #3498db, #3498db 2px, transparent 2px, transparent 10px ) `; document.body.appendChild(pattern); // Update text colors for better contrast on light background document.querySelectorAll('p, h1, h2, h3, h4, h5, h6').forEach(el => { // Only change if still using the dark theme colors if (getComputedStyle(el).color === 'rgb(216, 216, 255)' || getComputedStyle(el).color === 'rgb(143, 143, 183)') { el.style.color = '#505050'; } }); } function enhanceHeroSection() { const heroSection = document.querySelector('.hero'); if (!heroSection) return; // Remove any existing background if (heroSection.style.backgroundImage.includes('stars-bg.jpg')) { heroSection.style.backgroundImage = 'none'; } // Create a sky gradient background heroSection.style.background = 'linear-gradient(to bottom, #87CEEB 0%, #e6f7ff 100%)'; heroSection.style.position = 'relative'; heroSection.style.overflow = 'hidden'; // Create animation container const animationContainer = document.createElement('div'); animationContainer.className = 'drone-animation-container'; animationContainer.style.position = 'absolute'; animationContainer.style.top = '0'; animationContainer.style.left = '0'; animationContainer.style.width = '100%'; animationContainer.style.height = '100%'; animationContainer.style.pointerEvents = 'none'; animationContainer.style.zIndex = '1'; heroSection.appendChild(animationContainer); // Add roof silhouette const roofSilhouette = document.createElement('div'); roofSilhouette.className = 'roof-silhouette'; roofSilhouette.style.position = 'absolute'; roofSilhouette.style.bottom = '0'; roofSilhouette.style.left = '0'; roofSilhouette.style.width = '100%'; roofSilhouette.style.height = '20%'; roofSilhouette.style.background = 'url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjAwIDIwMCI+PHBhdGggZD0iTTAgMjAwVjE1MEg1MEwxMDAgMTAwTDE1MCAxNTBIMjAwTDI1MCAxMDBMMzAwIDE1MEgzNTBMNDAwIDUwTDQ1MCAxNTBINTAwTDU1MCAxMDBMNjAwIDE1MEg2NTBMNzAwIDEwMEw3NTAgMTUwSDgwMEw4NTAgNTBMOTAwIDE1MEg5NTBMMTAwMCAxMDBMMTA1MCAxNTBIMTEwMEwxMTUwIDEwMEwxMjAwIDE1MFYyMDBIMFoiIGZpbGw9IiNlMGUwZTAiIGZpbGwtb3BhY2l0eT0iMC40Ii8+PC9zdmc+")'; roofSilhouette.style.backgroundSize = 'cover'; roofSilhouette.style.zIndex = '0'; animationContainer.appendChild(roofSilhouette); // Create multiple drones with spray effects createCleaningDrone(animationContainer, 20, 30, -1, 20); createCleaningDrone(animationContainer, 60, 20, 1, 25); createCleaningDrone(animationContainer, 40, 50, -1, 30); // Add keyframes for animations addDroneAnimationStyles(); } function createCleaningDrone(container, startX, startY, direction, duration) { // Create drone container const droneElement = document.createElement('div'); droneElement.className = 'cleaning-drone'; droneElement.style.position = 'absolute'; droneElement.style.left = `${startX}%`; droneElement.style.top = `${startY}%`; droneElement.style.width = '60px'; droneElement.style.height = '60px'; droneElement.style.zIndex = '2'; // Calculate unique animation name const animationName = `drone-path-${startX}-${startY}`; droneElement.style.animation = `${animationName} ${duration}s linear infinite`; // Create drone body const droneBody = document.createElement('div'); droneBody.className = 'drone-body'; droneBody.style.position = 'relative'; droneBody.style.width = '40px'; droneBody.style.height = '40px'; droneBody.style.borderRadius = '50%'; droneBody.style.backgroundColor = '#3498db'; droneBody.style.border = '2px solid #2980b9'; droneBody.style.boxShadow = '0 2px 10px rgba(0, 0, 0, 0.2)'; droneBody.style.margin = '0 auto'; droneBody.style.zIndex = '2'; droneElement.appendChild(droneBody); // Add central hub const droneHub = document.createElement('div'); droneHub.className = 'drone-hub'; droneHub.style.position = 'absolute'; droneHub.style.top = '50%'; droneHub.style.left = '50%'; droneHub.style.width = '15px'; droneHub.style.height = '15px'; droneHub.style.borderRadius = '50%'; droneHub.style.backgroundColor = '#fff'; droneHub.style.transform = 'translate(-50%, -50%)'; droneHub.style.zIndex = '3'; droneBody.appendChild(droneHub); // Add propellers for (let i = 0; i < 4; i++) { const propContainer = document.createElement('div'); propContainer.className = 'propeller-container'; propContainer.style.position = 'absolute'; propContainer.style.width = '15px'; propContainer.style.height = '15px'; // Position propellers around drone switch(i) { case 0: // top left propContainer.style.top = '-10px'; propContainer.style.left = '-10px'; break; case 1: // top right propContainer.style.top = '-10px'; propContainer.style.right = '-10px'; break; case 2: // bottom left propContainer.style.bottom = '-10px'; propContainer.style.left = '-10px'; break; case 3: // bottom right propContainer.style.bottom = '-10px'; propContainer.style.right = '-10px'; break; } // Create propeller const propeller = document.createElement('div'); propeller.className = 'propeller'; propeller.style.width = '100%'; propeller.style.height = '100%'; propeller.style.borderRadius = '50%'; propeller.style.borderTop = '2px solid rgba(255,255,255,0.8)'; propeller.style.borderLeft = '2px solid rgba(255,255,255,0.6)'; propeller.style.animation = 'spin-propeller 0.15s linear infinite'; propContainer.appendChild(propeller); droneBody.appendChild(propContainer); } // Create water spray effect const waterSpray = document.createElement('div'); waterSpray.className = 'water-spray'; waterSpray.style.position = 'absolute'; waterSpray.style.bottom = '-20px'; waterSpray.style.left = '50%'; waterSpray.style.transform = 'translateX(-50%)'; waterSpray.style.width = '30px'; waterSpray.style.height = '50px'; waterSpray.style.zIndex = '1'; droneElement.appendChild(waterSpray); // Add water droplets to the spray for (let i = 0; i < 12; i++) { const droplet = document.createElement('div'); droplet.className = 'water-droplet'; droplet.style.position = 'absolute'; droplet.style.width = `${3 + Math.random() * 3}px`; droplet.style.height = `${5 + Math.random() * 7}px`; droplet.style.backgroundColor = 'rgba(173, 216, 230, 0.7)'; droplet.style.borderRadius = '50%'; // Randomize position within spray const angle = Math.random() * 30 - 15; // -15 to 15 degrees const distance = 5 + Math.random() * 45; // 5 to 50px droplet.style.top = `${distance}px`; droplet.style.left = '50%'; droplet.style.transform = `translateX(-50%) rotate(${angle}deg)`; // Different animation duration for each droplet const fallDuration = 0.5 + Math.random() * 0.5; droplet.style.animation = `fall-droplet ${fallDuration}s infinite linear`; waterSpray.appendChild(droplet); } // Create path animation for this specific drone const keyframesStyle = document.createElement('style'); keyframesStyle.innerHTML = ` @keyframes ${animationName} { 0% { transform: translateX(${direction > 0 ? '-100px' : '100vw'}) translateY(0px) rotate(${direction > 0 ? '0deg' : '180deg'}); } 25% { transform: translateX(${direction > 0 ? 'calc(20vw)' : 'calc(80vw - 100px)'}) translateY(-20px) rotate(${direction > 0 ? '0deg' : '180deg'}); } 50% { transform: translateX(${direction > 0 ? 'calc(40vw)' : 'calc(60vw - 100px)'}) translateY(30px) rotate(${direction > 0 ? '0deg' : '180deg'}); } 75% { transform: translateX(${direction > 0 ? 'calc(60vw)' : 'calc(40vw - 100px)'}) translateY(-15px) rotate(${direction > 0 ? '0deg' : '180deg'}); } 100% { transform: translateX(${direction > 0 ? '100vw' : '-100px'}) translateY(10px) rotate(${direction > 0 ? '0deg' : '180deg'}); } } `; document.head.appendChild(keyframesStyle); container.appendChild(droneElement); } function addDroneAnimationStyles() { const styleSheet = document.createElement('style'); styleSheet.innerHTML = ` @keyframes spin-propeller { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } @keyframes fall-droplet { 0% { opacity: 0.8; transform: translateX(-50%) translateY(0) scale(1); } 100% { opacity: 0; transform: translateX(-50%) translateY(30px) scale(0.5); } } `; document.head.appendChild(styleSheet); } function enhanceServiceCards() { const serviceCards = document.querySelectorAll('.service-card'); if (!serviceCards.length) return; serviceCards.forEach(card => { // Update card styling to match clean theme card.style.backgroundColor = 'white'; card.style.borderRadius = '10px'; card.style.boxShadow = '0 10px 30px rgba(0, 0, 0, 0.1)'; card.style.border = '1px solid rgba(0, 0, 0, 0.05)'; card.style.overflow = 'hidden'; // Add water droplet accent at the top const waterAccent = document.createElement('div'); waterAccent.className = 'water-accent'; waterAccent.style.height = '5px'; waterAccent.style.width = '100%'; waterAccent.style.position = 'absolute'; waterAccent.style.top = '0'; waterAccent.style.left = '0'; waterAccent.style.background = 'linear-gradient(90deg, #3498db, #00c2cb)'; card.prepend(waterAccent); // Add subtle cleaning pattern to each card addCleaningIconToCard(card); }); } function addCleaningIconToCard(card) { // Create a container for the icon const iconContainer = document.createElement('div'); iconContainer.className = 'cleaning-icon'; iconContainer.style.position = 'absolute'; iconContainer.style.top = '15px'; iconContainer.style.right = '15px'; iconContainer.style.width = '30px'; iconContainer.style.height = '30px'; iconContainer.style.opacity = '0.1'; // Randomly choose between different cleaning icons const icons = [ // Water droplet ``, // Spray bottle ``, // Drone `` ]; // Choose a random icon iconContainer.innerHTML = icons[Math.floor(Math.random() * icons.length)]; card.appendChild(iconContainer); } })();