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
487 lines
22 KiB
JavaScript
487 lines
22 KiB
JavaScript
/**
|
|
* Drone Image Animation with New Background
|
|
* Uses a single image background with the drone flying over the roof
|
|
*/
|
|
(function() {
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Only run on pages that have a hero section
|
|
const heroSection = document.querySelector('.hero');
|
|
if (heroSection) {
|
|
// Remove any existing backgrounds or animations
|
|
if (heroSection.style.backgroundImage) {
|
|
heroSection.style.backgroundImage = 'none';
|
|
}
|
|
|
|
// Remove any existing animation containers
|
|
const existingAnimations = heroSection.querySelectorAll('.drone-animation-container, .animation-container, .roof-cleaning-animation');
|
|
existingAnimations.forEach(el => el.remove());
|
|
|
|
// Create our animation with the new background
|
|
createAnimationWithSingleBackground(heroSection);
|
|
}
|
|
});
|
|
|
|
function createAnimationWithSingleBackground(container) {
|
|
// Create animation container with more aggressive full-width styling
|
|
const animationContainer = document.createElement('div');
|
|
animationContainer.className = 'drone-animation-container';
|
|
|
|
// Position absolutely with negative margins to escape any parent padding
|
|
animationContainer.style.position = 'absolute';
|
|
animationContainer.style.top = '0';
|
|
animationContainer.style.left = '0';
|
|
animationContainer.style.right = '0'; // Add right: 0 to ensure full width
|
|
animationContainer.style.width = '100vw'; // Use viewport width
|
|
animationContainer.style.maxWidth = '100vw'; // Override any max-width restrictions
|
|
animationContainer.style.marginLeft = 'calc(50% - 50vw)'; // Center regardless of parent padding
|
|
animationContainer.style.marginRight = 'calc(50% - 50vw)'; // Center regardless of parent padding
|
|
animationContainer.style.height = '100%';
|
|
animationContainer.style.overflow = 'hidden';
|
|
animationContainer.style.pointerEvents = 'none';
|
|
animationContainer.style.zIndex = '1';
|
|
|
|
// Add CSS to fix any scrollbar issues
|
|
const styleFixForScrollbar = document.createElement('style');
|
|
styleFixForScrollbar.textContent = `
|
|
html, body {
|
|
overflow-x: hidden;
|
|
width: 100%;
|
|
position: relative;
|
|
}
|
|
.hero {
|
|
width: 100%;
|
|
max-width: 100%;
|
|
overflow: hidden;
|
|
padding-left: 0 !important;
|
|
padding-right: 0 !important;
|
|
}
|
|
`;
|
|
document.head.appendChild(styleFixForScrollbar);
|
|
|
|
// Fix mobile white space by adjusting the parent container on mobile
|
|
if (window.innerWidth <= 768) {
|
|
// Remove potential white space in parent container
|
|
container.style.paddingBottom = '0';
|
|
container.style.marginBottom = '0';
|
|
}
|
|
|
|
// Create background using the new image
|
|
createFullBackground(animationContainer);
|
|
|
|
// Create drone elements that will fly over the roof
|
|
createFlyingDrones(animationContainer);
|
|
|
|
// Add everything to the container
|
|
container.appendChild(animationContainer);
|
|
|
|
// Add animation styles
|
|
addAnimationStyles();
|
|
|
|
// Add resize listener to adjust for screen size changes
|
|
window.addEventListener('resize', function() {
|
|
adjustForScreenSize(animationContainer);
|
|
});
|
|
|
|
// Initial adjustment for screen size
|
|
adjustForScreenSize(animationContainer);
|
|
|
|
// Position the hero content (text) in the sky area
|
|
positionHeroContent(container);
|
|
}
|
|
|
|
function createFullBackground(container) {
|
|
// Create the full background with enhanced full-width styling
|
|
const backgroundElement = document.createElement('div');
|
|
backgroundElement.className = 'animation-background';
|
|
backgroundElement.style.position = 'absolute';
|
|
backgroundElement.style.top = '0';
|
|
backgroundElement.style.left = '0';
|
|
backgroundElement.style.right = '0'; // Add right: 0
|
|
backgroundElement.style.width = '100vw'; // Use viewport width
|
|
backgroundElement.style.maxWidth = 'none'; // No max width restrictions
|
|
backgroundElement.style.height = '100%';
|
|
backgroundElement.style.backgroundImage = 'url("images/animation_background1.png")';
|
|
backgroundElement.style.backgroundSize = 'cover';
|
|
backgroundElement.style.backgroundPosition = 'center center';
|
|
backgroundElement.style.backgroundRepeat = 'no-repeat';
|
|
backgroundElement.style.backgroundColor = '#75b0cc';
|
|
backgroundElement.style.zIndex = '1';
|
|
|
|
// Add subtle overlay to improve text visibility
|
|
const overlay = document.createElement('div');
|
|
overlay.style.position = 'absolute';
|
|
overlay.style.top = '0';
|
|
overlay.style.left = '0';
|
|
overlay.style.width = '100%';
|
|
overlay.style.height = '100%';
|
|
overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.1)'; /* Subtle darkening */
|
|
overlay.style.zIndex = '2';
|
|
backgroundElement.appendChild(overlay);
|
|
|
|
container.appendChild(backgroundElement);
|
|
|
|
// Add resize event listener for responsive adjustments
|
|
window.addEventListener('resize', function() {
|
|
adjustBackground(backgroundElement);
|
|
});
|
|
|
|
// Initial adjustment
|
|
adjustBackground(backgroundElement);
|
|
}
|
|
|
|
function adjustBackground(backgroundElement) {
|
|
const isMobile = window.innerWidth <= 768;
|
|
const isPortrait = window.innerHeight > window.innerWidth;
|
|
|
|
if (isMobile) {
|
|
if (isPortrait) {
|
|
// Portrait mobile - fix grey area by using cover and adjusting transform
|
|
backgroundElement.style.backgroundSize = 'cover';
|
|
backgroundElement.style.transform = 'translateY(-15%)'; // Move image up instead of using background-position
|
|
backgroundElement.style.height = '100%'; // Ensure full height
|
|
} else {
|
|
// Landscape mobile - also fix using transform
|
|
backgroundElement.style.backgroundSize = 'cover';
|
|
backgroundElement.style.transform = 'translateY(-10%)';
|
|
backgroundElement.style.height = '100%';
|
|
}
|
|
} else {
|
|
// Desktop - standard positioning
|
|
backgroundElement.style.backgroundSize = 'cover';
|
|
backgroundElement.style.transform = 'none';
|
|
backgroundElement.style.backgroundPosition = 'center center';
|
|
}
|
|
}
|
|
|
|
function positionHeroContent(container) {
|
|
// Get the hero content (text)
|
|
const heroContent = container.querySelector('.hero-content');
|
|
if (heroContent) {
|
|
// Split the content: Title in sky, rest at top of roof
|
|
const headline = heroContent.querySelector('h2');
|
|
const otherContent = document.createElement('div');
|
|
otherContent.className = 'hero-secondary-content';
|
|
|
|
// Get all other elements except the headline
|
|
const subheading = heroContent.querySelector('p');
|
|
const ctaButton = heroContent.querySelector('.btn-primary');
|
|
|
|
// Set styles for the main container
|
|
heroContent.style.position = 'relative';
|
|
heroContent.style.zIndex = '5';
|
|
heroContent.style.display = 'flex';
|
|
heroContent.style.flexDirection = 'column';
|
|
heroContent.style.alignItems = 'center';
|
|
heroContent.style.justifyContent = 'space-between';
|
|
heroContent.style.height = '100%';
|
|
heroContent.style.textShadow = '0 2px 4px rgba(0, 0, 0, 0.3)';
|
|
|
|
// Style headline to be in sky - make consistent across all views
|
|
if (headline) {
|
|
headline.style.color = '#ffffff';
|
|
headline.style.margin = '0 auto 2rem';
|
|
headline.style.maxWidth = '100%'; // Changed from 90% to 100% for better text wrapping
|
|
headline.style.textAlign = 'center';
|
|
headline.style.position = 'relative';
|
|
headline.style.zIndex = '6';
|
|
headline.style.fontSize = window.innerWidth <= 480 ? '1.5rem' : (window.innerWidth <= 768 ? '1.8rem' : '3rem'); // Reduced from 1.7rem to 1.5rem for smallest screens
|
|
headline.style.lineHeight = '1.3'; // Add line height for better text spacing
|
|
headline.style.width = '100%'; // Ensure full width
|
|
headline.style.wordWrap = 'break-word'; // Improve word wrapping
|
|
headline.style.hyphens = 'none'; // Changed from 'auto' to 'none'
|
|
headline.style.wordBreak = 'keep-all'; // Prevent words from breaking
|
|
headline.style.whiteSpace = 'normal'; // Allow normal wrapping but prevent word splitting
|
|
|
|
// More mobile-friendly initial positioning
|
|
headline.style.marginTop = window.innerWidth <= 768 ? '-3rem' : '-8rem';
|
|
}
|
|
|
|
// Move other content to a separate container
|
|
if (subheading && ctaButton) {
|
|
// Remove elements from their current position
|
|
subheading.remove();
|
|
ctaButton.remove();
|
|
|
|
// Add them to the new container
|
|
otherContent.appendChild(subheading);
|
|
otherContent.appendChild(ctaButton);
|
|
|
|
// Style the subheading
|
|
subheading.style.color = '#ffffff';
|
|
subheading.style.marginBottom = '1.5rem';
|
|
|
|
// Style the container for other content
|
|
otherContent.style.display = 'flex';
|
|
otherContent.style.flexDirection = 'column';
|
|
otherContent.style.alignItems = 'center';
|
|
otherContent.style.position = 'relative';
|
|
otherContent.style.zIndex = '6';
|
|
|
|
// Add the container to the hero content
|
|
heroContent.appendChild(otherContent);
|
|
}
|
|
|
|
// Adjust positions for different screen sizes
|
|
adjustHeroContentPositioning(heroContent, headline, otherContent);
|
|
window.addEventListener('resize', function() {
|
|
adjustHeroContentPositioning(heroContent, headline, otherContent);
|
|
});
|
|
}
|
|
}
|
|
|
|
function adjustHeroContentPositioning(heroContent, headline, otherContent) {
|
|
const isMobile = window.innerWidth <= 768;
|
|
const isPortrait = window.innerHeight > window.innerWidth;
|
|
const isSmallPhone = window.innerWidth <= 480;
|
|
|
|
// Apply different positioning based on device type and size
|
|
if (headline) {
|
|
if (isMobile) {
|
|
if (isPortrait) {
|
|
// Portrait mobile - adjust based on device height
|
|
const viewportHeight = window.innerHeight;
|
|
if (viewportHeight <= 600) {
|
|
// Very small device
|
|
headline.style.marginTop = '-1rem';
|
|
} else if (viewportHeight <= 800) {
|
|
// Medium device
|
|
headline.style.marginTop = '-2rem';
|
|
} else {
|
|
// Larger device
|
|
headline.style.marginTop = '-3rem';
|
|
}
|
|
} else {
|
|
// Landscape mobile
|
|
headline.style.marginTop = '-2rem';
|
|
}
|
|
} else {
|
|
// Desktop - keep as is
|
|
headline.style.marginTop = '-8rem';
|
|
}
|
|
}
|
|
|
|
if (otherContent) {
|
|
otherContent.style.marginTop = 'auto';
|
|
|
|
if (isMobile) {
|
|
if (isPortrait) {
|
|
// Portrait mobile - adjust based on device height
|
|
const viewportHeight = window.innerHeight;
|
|
if (viewportHeight <= 600) {
|
|
// More compact spacing for small devices
|
|
otherContent.style.marginBottom = '3rem';
|
|
} else if (viewportHeight <= 800) {
|
|
otherContent.style.marginBottom = '4rem';
|
|
} else {
|
|
otherContent.style.marginBottom = '5rem';
|
|
}
|
|
|
|
// Adjust spacing between elements for small devices
|
|
if (isSmallPhone) {
|
|
const subheading = otherContent.querySelector('p');
|
|
if (subheading) {
|
|
subheading.style.marginBottom = '1rem';
|
|
}
|
|
}
|
|
} else {
|
|
// Landscape mobile
|
|
otherContent.style.marginBottom = '3rem';
|
|
}
|
|
} else {
|
|
// Desktop
|
|
otherContent.style.marginBottom = '5rem';
|
|
}
|
|
}
|
|
}
|
|
|
|
function adjustHeroContent(heroContent) {
|
|
// This function is replaced by the more specific positioning function above
|
|
// Keep it for compatibility but it no longer needs to do anything
|
|
}
|
|
|
|
function createFlyingDrones(container) {
|
|
// Create drone path container
|
|
const dronePathContainer = document.createElement('div');
|
|
dronePathContainer.className = 'drone-path-container';
|
|
dronePathContainer.style.position = 'absolute';
|
|
dronePathContainer.style.top = '0';
|
|
dronePathContainer.style.left = '0';
|
|
dronePathContainer.style.width = '100%';
|
|
dronePathContainer.style.height = '100%';
|
|
dronePathContainer.style.zIndex = '10';
|
|
container.appendChild(dronePathContainer);
|
|
|
|
// Create drone with responsive sizing
|
|
createDrone(dronePathContainer, 'drone-path-1', 0);
|
|
}
|
|
|
|
function createDrone(container, pathClass, startDelay = 0, duration = 30) {
|
|
// Create drone element using the specified drone image
|
|
const droneElement = document.createElement('div');
|
|
droneElement.className = `animated-drone ${pathClass}`;
|
|
droneElement.style.position = 'absolute';
|
|
droneElement.style.width = '440px'; // Will be adjusted for mobile
|
|
droneElement.style.height = '300px'; // Will be adjusted for mobile
|
|
droneElement.style.top = '45%'; // Position for new background
|
|
droneElement.style.left = '-450px';
|
|
droneElement.style.zIndex = '15'; // Above all other elements
|
|
droneElement.style.animation = `${pathClass} ${duration}s linear infinite`;
|
|
droneElement.style.animationDelay = `${startDelay}s`;
|
|
|
|
// Add the drone image
|
|
const droneImage = document.createElement('img');
|
|
droneImage.src = 'images/spraying_drone4.png';
|
|
droneImage.alt = 'Dachreinigungsdrohne';
|
|
droneImage.style.width = '100%';
|
|
droneImage.style.height = 'auto';
|
|
droneImage.style.filter = 'drop-shadow(0 15px 30px rgba(0,0,0,0.25))';
|
|
droneElement.appendChild(droneImage);
|
|
|
|
container.appendChild(droneElement);
|
|
}
|
|
|
|
function adjustForScreenSize(container) {
|
|
const isMobile = window.innerWidth <= 768;
|
|
const isPortrait = window.innerHeight > window.innerWidth;
|
|
|
|
// Fix white space issue on mobile
|
|
if (isMobile) {
|
|
// Adjust parent container (hero section)
|
|
const heroSection = container.closest('.hero');
|
|
if (heroSection) {
|
|
heroSection.style.paddingBottom = '0';
|
|
heroSection.style.marginBottom = '0';
|
|
// Ensure full height to bottom of viewport on mobile
|
|
container.style.minHeight = '100%';
|
|
}
|
|
|
|
// Adjust the main background element to extend fully
|
|
const backgroundEl = container.querySelector('.animation-background');
|
|
if (backgroundEl) {
|
|
backgroundEl.style.bottom = '0';
|
|
backgroundEl.style.height = '100%';
|
|
// Add extra height to cover any potential gaps
|
|
backgroundEl.style.marginBottom = '-2px';
|
|
}
|
|
}
|
|
|
|
const drones = container.querySelectorAll('.animated-drone');
|
|
|
|
// Adjust drone sizes
|
|
drones.forEach(drone => {
|
|
if (isMobile) {
|
|
if (isPortrait) {
|
|
// Portrait mobile - smaller drone
|
|
drone.style.width = '150px';
|
|
drone.style.height = '100px';
|
|
} else {
|
|
// Landscape mobile
|
|
drone.style.width = '180px';
|
|
drone.style.height = '120px';
|
|
}
|
|
} else {
|
|
// Desktop size
|
|
drone.style.width = '440px';
|
|
drone.style.height = '300px';
|
|
}
|
|
});
|
|
|
|
// Adjust background
|
|
const background = container.querySelector('.animation-background');
|
|
if (background) {
|
|
adjustBackground(background);
|
|
}
|
|
|
|
// Add headline adjustment on resize
|
|
const headline = document.querySelector('.hero-content h2');
|
|
if (headline) {
|
|
// Adjust font size based on screen width for better text wrapping
|
|
if (window.innerWidth <= 480) {
|
|
headline.style.fontSize = '1.5rem';
|
|
headline.style.lineHeight = '1.3';
|
|
headline.style.maxWidth = '100%';
|
|
headline.style.padding = '0 0.5rem'; // Add padding for smallest screens
|
|
headline.style.hyphens = 'none';
|
|
headline.style.wordBreak = 'keep-all';
|
|
headline.style.whiteSpace = 'normal';
|
|
} else if (window.innerWidth <= 768) {
|
|
headline.style.fontSize = '1.8rem';
|
|
headline.style.lineHeight = '1.3';
|
|
headline.style.maxWidth = '100%';
|
|
headline.style.hyphens = 'none';
|
|
headline.style.wordBreak = 'keep-all';
|
|
headline.style.whiteSpace = 'normal';
|
|
} else {
|
|
headline.style.fontSize = '3rem';
|
|
headline.style.lineHeight = '1.2';
|
|
headline.style.maxWidth = '90%';
|
|
headline.style.hyphens = 'none';
|
|
headline.style.wordBreak = 'keep-all';
|
|
headline.style.whiteSpace = 'normal';
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add a resize event listener to handle orientation changes
|
|
window.addEventListener('resize', function() {
|
|
const animationContainer = document.querySelector('.drone-animation-container');
|
|
if (animationContainer) {
|
|
adjustForScreenSize(animationContainer);
|
|
}
|
|
});
|
|
|
|
function addAnimationStyles() {
|
|
// Create style element if it doesn't exist
|
|
if (!document.getElementById('drone-animation-styles')) {
|
|
const styleElement = document.createElement('style');
|
|
styleElement.id = 'drone-animation-styles';
|
|
|
|
// Add responsive animations with adjusted drone path to match new background
|
|
styleElement.innerHTML = `
|
|
@keyframes drone-path-1 {
|
|
/* First half - path adjusted for new background */
|
|
0% { left: -450px; top: 45%; transform: rotate(0deg); }
|
|
5% { left: 10%; top: 43%; transform: rotate(-5deg); }
|
|
10% { left: 20%; top: 45%; transform: rotate(0deg); }
|
|
15% { left: 30%; top: 47%; transform: rotate(5deg); }
|
|
20% { left: 40%; top: 45%; transform: rotate(0deg); }
|
|
25% { left: 50%; top: 48%; transform: rotate(-3deg); }
|
|
30% { left: 60%; top: 50%; transform: rotate(0deg); }
|
|
35% { left: 70%; top: 52%; transform: rotate(3deg); }
|
|
40% { left: 80%; top: 50%; transform: rotate(0deg); }
|
|
45% { left: 90%; top: 48%; transform: rotate(-5deg); }
|
|
50% { left: 100%; top: 45%; transform: rotate(-10deg); }
|
|
|
|
/* Second half - return path */
|
|
55% { left: 90%; top: 48%; transform: rotate(-5deg) scaleX(-1); }
|
|
60% { left: 80%; top: 50%; transform: rotate(0deg) scaleX(-1); }
|
|
65% { left: 70%; top: 52%; transform: rotate(3deg) scaleX(-1); }
|
|
70% { left: 60%; top: 50%; transform: rotate(0deg) scaleX(-1); }
|
|
75% { left: 50%; top: 48%; transform: rotate(-3deg) scaleX(-1); }
|
|
80% { left: 40%; top: 45%; transform: rotate(0deg) scaleX(-1); }
|
|
85% { left: 30%; top: 47%; transform: rotate(5deg) scaleX(-1); }
|
|
90% { left: 20%; top: 45%; transform: rotate(0deg) scaleX(-1); }
|
|
95% { left: 10%; top: 43%; transform: rotate(-5deg) scaleX(-1); }
|
|
100% { left: -450px; top: 45%; transform: rotate(0deg) scaleX(-1); }
|
|
}
|
|
|
|
/* Mobile-specific animations */
|
|
@media (max-width: 768px) {
|
|
@keyframes drone-path-1 {
|
|
/* Adjusted path for mobile - fly higher to match the shifted background */
|
|
0% { left: -220px; top: 45%; transform: rotate(0deg); }
|
|
20% { left: 30%; top: 43%; transform: rotate(-5deg); }
|
|
40% { left: 70%; top: 47%; transform: rotate(5deg); }
|
|
50% { left: 100%; top: 45%; transform: rotate(-5deg); }
|
|
60% { left: 70%; top: 47%; transform: rotate(5deg) scaleX(-1); }
|
|
80% { left: 30%; top: 43%; transform: rotate(-5deg) scaleX(-1); }
|
|
100% { left: -220px; top: 45%; transform: rotate(0deg) scaleX(-1); }
|
|
}
|
|
}
|
|
`;
|
|
|
|
document.head.appendChild(styleElement);
|
|
}
|
|
}
|
|
})();
|