Files
luftglanz/js/background-patterns.js
Luftglanz ac7088c5ca Initial commit: Luftglanz drone website with integrated AI chat assistant
Features:
- Complete Luftglanz drone cleaning website
- AI chat assistant integrated with OpenAI API
- Expert product advice for AGO Quart and Mellerud cleaning products
- Formal German language support (Sie form)
- Secure PHP backend for API calls
- Responsive design with mobile support
- Product-specific knowledge base
- Safety statements from manufacturers
- Multi-page integration (index, products, services, contact)

Technical components:
- AI chat widget (js/ai-chat.js)
- Chat styling (css/components/ai-chat.css)
- Backend API (ai-chat-api.php)
- Product knowledge base with detailed specifications
- Demo and documentation files
2025-07-08 11:54:37 +02:00

335 lines
15 KiB
JavaScript

/**
* 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
`<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 20C16.4183 20 20 16.4183 20 12C20 7.58172 12 3 12 3C12 3 4 7.58172 4 12C4 16.4183 7.58172 20 12 20Z" fill="#3498db"/></svg>`,
// Spray bottle
`<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8 3H11V5H13V3H16V5H14V7H17L19 10V21H6V10L8 7H11V5H8V3ZM8 10V19H17V10L15.8 8H9.2L8 10Z" fill="#3498db"/></svg>`,
// Drone
`<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8C13.1046 8 14 7.10457 14 6C14 4.89543 13.1046 4 12 4C10.8954 4 10 4.89543 10 6C10 7.10457 10.8954 8 12 8Z" fill="#3498db"/><path d="M4 10C5.10457 10 6 9.10457 6 8C6 6.89543 5.10457 6 4 6C2.89543 6 2 6.89543 2 8C2 9.10457 2.89543 10 4 10Z" fill="#3498db"/><path d="M20 10C21.1046 10 22 9.10457 22 8C22 6.89543 21.1046 6 20 6C18.8954 6 18 6.89543 18 8C18 9.10457 18.8954 10 20 10Z" fill="#3498db"/><path d="M12 20C13.1046 20 14 19.1046 14 18C14 16.8954 13.1046 16 12 16C10.8954 16 10 16.8954 10 18C10 19.1046 10.8954 20 12 20Z" fill="#3498db"/><path d="M12 8V16M4 10L10 16M20 10L14 16" stroke="#3498db" stroke-width="2" stroke-linecap="round"/></svg>`
];
// Choose a random icon
iconContainer.innerHTML = icons[Math.floor(Math.random() * icons.length)];
card.appendChild(iconContainer);
}
})();