Spaces:
Build error
Build error
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>EcoLytics: Intelligent Hydrogen Economics Platform</title> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/gsap.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/ScrollTrigger.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/particles.js/2.0.0/particles.min.js"></script> | |
| <style> | |
| :root { | |
| --primary: #0F9D58; | |
| --secondary: #1E88E5; | |
| --dark: #121212; | |
| --light: #f5f5f7; | |
| --gradient: linear-gradient(135deg, #0F9D58 0%, #1E88E5 100%); | |
| } | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
| } | |
| body { | |
| background-color: var(--light); | |
| color: var(--dark); | |
| overflow-x: hidden; | |
| } | |
| section { | |
| padding: 80px 0; | |
| position: relative; | |
| } | |
| .container { | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| padding: 0 20px; | |
| } | |
| /* Hero Section */ | |
| .hero { | |
| min-height: 100vh; | |
| display: flex; | |
| align-items: center; | |
| position: relative; | |
| overflow: hidden; | |
| background: linear-gradient(rgba(0,0,0,0.7), rgba(0,0,0,0.7)), url('/api/placeholder/1920/1080') center/cover; | |
| } | |
| #particles-js { | |
| position: absolute; | |
| width: 100%; | |
| height: 100%; | |
| top: 0; | |
| left: 0; | |
| } | |
| .hero-content { | |
| position: relative; | |
| z-index: 2; | |
| color: white; | |
| max-width: 650px; | |
| } | |
| h1 { | |
| font-size: 4rem; | |
| margin-bottom: 20px; | |
| line-height: 1.1; | |
| background: var(--gradient); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| } | |
| .subtitle { | |
| font-size: 1.5rem; | |
| margin-bottom: 30px; | |
| font-weight: 300; | |
| line-height: 1.5; | |
| } | |
| .cta-button { | |
| display: inline-block; | |
| background: var(--gradient); | |
| color: white; | |
| padding: 15px 40px; | |
| border-radius: 50px; | |
| font-size: 1.2rem; | |
| font-weight: 500; | |
| text-decoration: none; | |
| box-shadow: 0 10px 20px rgba(0,0,0,0.1); | |
| transition: transform 0.3s, box-shadow 0.3s; | |
| } | |
| .cta-button:hover { | |
| transform: translateY(-3px); | |
| box-shadow: 0 15px 30px rgba(0,0,0,0.2); | |
| } | |
| /* Features Section */ | |
| .features { | |
| background-color: white; | |
| } | |
| .section-title { | |
| text-align: center; | |
| margin-bottom: 60px; | |
| } | |
| .section-title h2 { | |
| font-size: 2.5rem; | |
| margin-bottom: 15px; | |
| color: var(--primary); | |
| } | |
| .feature-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); | |
| gap: 40px; | |
| } | |
| .feature-card { | |
| background: white; | |
| border-radius: 15px; | |
| padding: 30px; | |
| box-shadow: 0 10px 30px rgba(0,0,0,0.05); | |
| transition: transform 0.3s; | |
| } | |
| .feature-card:hover { | |
| transform: translateY(-10px); | |
| } | |
| .feature-icon { | |
| width: 70px; | |
| height: 70px; | |
| background: var(--gradient); | |
| border-radius: 50%; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| margin-bottom: 25px; | |
| } | |
| .feature-icon svg { | |
| width: 35px; | |
| height: 35px; | |
| fill: white; | |
| } | |
| .feature-card h3 { | |
| font-size: 1.5rem; | |
| margin-bottom: 15px; | |
| color: var(--dark); | |
| } | |
| /* Process Section */ | |
| .process { | |
| background-color: #f9f9f9; | |
| overflow: hidden; | |
| } | |
| .process-container { | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| } | |
| .process-content { | |
| flex: 1; | |
| padding-right: 50px; | |
| } | |
| .process-visual { | |
| flex: 1; | |
| position: relative; | |
| height: 500px; | |
| } | |
| #electrolyzer-canvas { | |
| width: 100%; | |
| height: 100%; | |
| } | |
| .process-steps { | |
| margin-top: 40px; | |
| } | |
| .process-step { | |
| display: flex; | |
| margin-bottom: 30px; | |
| opacity: 0.5; | |
| transition: opacity 0.3s; | |
| } | |
| .process-step.active { | |
| opacity: 1; | |
| } | |
| .step-number { | |
| width: 40px; | |
| height: 40px; | |
| background: var(--gradient); | |
| border-radius: 50%; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| color: white; | |
| font-weight: bold; | |
| margin-right: 20px; | |
| flex-shrink: 0; | |
| } | |
| .step-content h4 { | |
| font-size: 1.3rem; | |
| margin-bottom: 10px; | |
| color: var(--primary); | |
| } | |
| /* Dashboard Preview */ | |
| .dashboard-preview { | |
| text-align: center; | |
| background: linear-gradient(135deg, #f9f9f9 0%, #e6e6e6 100%); | |
| padding: 100px 0; | |
| } | |
| .dashboard-image { | |
| max-width: 90%; | |
| margin: 0 auto; | |
| border-radius: 10px; | |
| box-shadow: 0 20px 40px rgba(0,0,0,0.15); | |
| transition: transform 0.3s; | |
| } | |
| .dashboard-image:hover { | |
| transform: scale(1.02); | |
| } | |
| /* CTA Section */ | |
| .cta-section { | |
| background: var(--gradient); | |
| color: white; | |
| text-align: center; | |
| padding: 100px 0; | |
| } | |
| .cta-section h2 { | |
| font-size: 3rem; | |
| margin-bottom: 20px; | |
| } | |
| .cta-section p { | |
| font-size: 1.3rem; | |
| max-width: 700px; | |
| margin: 0 auto 40px; | |
| opacity: 0.9; | |
| } | |
| .cta-buttons { | |
| display: flex; | |
| justify-content: center; | |
| gap: 20px; | |
| } | |
| .secondary-cta { | |
| background: transparent; | |
| border: 2px solid white; | |
| } | |
| /* Footer */ | |
| footer { | |
| background: var(--dark); | |
| color: white; | |
| padding: 60px 0 30px; | |
| } | |
| .footer-content { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); | |
| gap: 40px; | |
| margin-bottom: 60px; | |
| } | |
| .footer-column h4 { | |
| font-size: 1.2rem; | |
| margin-bottom: 20px; | |
| color: var(--primary); | |
| } | |
| .footer-links a { | |
| display: block; | |
| color: rgba(255,255,255,0.7); | |
| margin-bottom: 10px; | |
| text-decoration: none; | |
| transition: color 0.3s; | |
| } | |
| .footer-links a:hover { | |
| color: white; | |
| } | |
| .copyright { | |
| text-align: center; | |
| padding-top: 30px; | |
| border-top: 1px solid rgba(255,255,255,0.1); | |
| color: rgba(255,255,255,0.5); | |
| font-size: 0.9rem; | |
| } | |
| /* Animation Classes */ | |
| .fade-in { | |
| opacity: 0; | |
| transform: translateY(30px); | |
| transition: opacity 0.6s, transform 0.6s; | |
| } | |
| .fade-in.active { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| /* Responsive Styles */ | |
| @media (max-width: 768px) { | |
| h1 { | |
| font-size: 3rem; | |
| } | |
| .process-container { | |
| flex-direction: column; | |
| } | |
| .process-content { | |
| padding-right: 0; | |
| margin-bottom: 50px; | |
| text-align: center; | |
| } | |
| .process-visual { | |
| height: 400px; | |
| width: 100%; | |
| } | |
| .cta-buttons { | |
| flex-direction: column; | |
| align-items: center; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- Hero Section --> | |
| <section class="hero"> | |
| <div id="particles-js"></div> | |
| <div class="container"> | |
| <div class="hero-content"> | |
| <h1>EcoLytics</h1> | |
| <p class="subtitle">Intelligent Hydrogen Economics Platform powered by AI to revolutionize techno-economic analysis for green hydrogen projects.</p> | |
| <a href="#features" class="cta-button">Explore Features</a> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Features Section --> | |
| <section id="features" class="features"> | |
| <div class="container"> | |
| <div class="section-title fade-in"> | |
| <h2>Intelligent Analysis Features</h2> | |
| <p>Reimagining green hydrogen project planning with advanced AI capabilities</p> | |
| </div> | |
| <div class="feature-grid"> | |
| <div class="feature-card fade-in"> | |
| <div class="feature-icon"> | |
| <svg viewBox="0 0 24 24"> | |
| <path d="M16 6l2.29 2.29-4.88 4.88-4-4L2 16.59 3.41 18l6-6 4 4 6.3-6.29L22 12V6z"></path> | |
| </svg> | |
| </div> | |
| <h3>Predictive Cost Modeling</h3> | |
| <p>ML algorithms forecast CAPEX/OPEX with 94% accuracy, accounting for technology evolution curves and market dynamics.</p> | |
| </div> | |
| <div class="feature-card fade-in"> | |
| <div class="feature-icon"> | |
| <svg viewBox="0 0 24 24"> | |
| <path d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"></path> | |
| </svg> | |
| </div> | |
| <h3>Configuration Optimizer</h3> | |
| <p>Suggests optimal electrolyzer setup based on location, scale, and grid characteristics with dynamic sensitivity analysis.</p> | |
| </div> | |
| <div class="feature-card fade-in"> | |
| <div class="feature-icon"> | |
| <svg viewBox="0 0 24 24"> | |
| <path d="M3 13h8V3H3v10zm0 8h8v-6H3v6zm10 0h8V11h-8v10zm0-18v6h8V3h-8z"></path> | |
| </svg> | |
| </div> | |
| <h3>Interactive Visualization</h3> | |
| <p>Dynamic dashboards for real-time ROI scenario planning and cost breakdown across the entire hydrogen value chain.</p> | |
| </div> | |
| <div class="feature-card fade-in"> | |
| <div class="feature-icon"> | |
| <svg viewBox="0 0 24 24"> | |
| <path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14zM7 10h2v7H7zm4-3h2v10h-2zm4 6h2v4h-2z"></path> | |
| </svg> | |
| </div> | |
| <h3>Policy Impact Simulator</h3> | |
| <p>Evaluates how incentives and regulations affect project economics with regional comparison tool for global investment decisions.</p> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Process Section --> | |
| <section class="process"> | |
| <div class="container process-container"> | |
| <div class="process-content fade-in"> | |
| <h2>Electrolysis Optimization Process</h2> | |
| <p>Our AI-powered platform analyzes every aspect of the green hydrogen production process to maximize efficiency and minimize costs.</p> | |
| <div class="process-steps"> | |
| <div class="process-step active" data-step="1"> | |
| <div class="step-number">1</div> | |
| <div class="step-content"> | |
| <h4>Input Configuration</h4> | |
| <p>Define project parameters including location, capacity, electrolyzer type, and renewable energy sources.</p> | |
| </div> | |
| </div> | |
| <div class="process-step" data-step="2"> | |
| <div class="step-number">2</div> | |
| <div class="step-content"> | |
| <h4>AI Analysis</h4> | |
| <p>Our machine learning models analyze your configuration against hundreds of market variables and historical data.</p> | |
| </div> | |
| </div> | |
| <div class="process-step" data-step="3"> | |
| <div class="step-number">3</div> | |
| <div class="step-content"> | |
| <h4>Optimization Recommendations</h4> | |
| <p>Receive detailed recommendations for optimizing electrolyzer efficiency, energy usage, and overall economics.</p> | |
| </div> | |
| </div> | |
| <div class="process-step" data-step="4"> | |
| <div class="step-number">4</div> | |
| <div class="step-content"> | |
| <h4>Scenario Planning</h4> | |
| <p>Explore multiple scenarios to understand sensitivities and identify the most robust configuration for your project.</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="process-visual fade-in"> | |
| <canvas id="electrolyzer-canvas"></canvas> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Dashboard Preview --> | |
| <section class="dashboard-preview"> | |
| <div class="container"> | |
| <div class="section-title fade-in"> | |
| <h2>Intelligent Dashboard</h2> | |
| <p>Visualize complex hydrogen economics with our intuitive dashboard</p> | |
| </div> | |
| <img src="/api/placeholder/1200/800" alt="EcoLytics Dashboard" class="dashboard-image fade-in"> | |
| </div> | |
| </section> | |
| <!-- CTA Section --> | |
| <section class="cta-section"> | |
| <div class="container"> | |
| <h2 class="fade-in">Ready to Transform Your Hydrogen Projects?</h2> | |
| <p class="fade-in">Join the hydrogen revolution with AI-powered techno-economic analysis that gives you the competitive edge.</p> | |
| <div class="cta-buttons fade-in"> | |
| <a href="#" class="cta-button">Request a Demo</a> | |
| <a href="#" class="cta-button secondary-cta">Learn More</a> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Footer --> | |
| <footer> | |
| <div class="container"> | |
| <div class="footer-content"> | |
| <div class="footer-column"> | |
| <h4>EcoLytics</h4> | |
| <div class="footer-links"> | |
| <a href="#">About Us</a> | |
| <a href="#">Our Team</a> | |
| <a href="#">Careers</a> | |
| <a href="#">Contact</a> | |
| </div> | |
| </div> | |
| <div class="footer-column"> | |
| <h4>Product</h4> | |
| <div class="footer-links"> | |
| <a href="#">Features</a> | |
| <a href="#">Pricing</a> | |
| <a href="#">Case Studies</a> | |
| <a href="#">API Documentation</a> | |
| </div> | |
| </div> | |
| <div class="footer-column"> | |
| <h4>Resources</h4> | |
| <div class="footer-links"> | |
| <a href="#">Blog</a> | |
| <a href="#">Whitepapers</a> | |
| <a href="#">Webinars</a> | |
| <a href="#">Knowledge Base</a> | |
| </div> | |
| </div> | |
| <div class="footer-column"> | |
| <h4>Legal</h4> | |
| <div class="footer-links"> | |
| <a href="#">Privacy Policy</a> | |
| <a href="#">Terms of Service</a> | |
| <a href="#">Cookie Policy</a> | |
| <a href="#">GDPR Compliance</a> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="copyright"> | |
| © 2025 EcoLytics. All rights reserved. | |
| </div> | |
| </div> | |
| </footer> | |
| <script> | |
| // Initialization | |
| document.addEventListener('DOMContentLoaded', () => { | |
| // Initialize GSAP ScrollTrigger | |
| gsap.registerPlugin(ScrollTrigger); | |
| // Fade In Animations | |
| const fadeElements = document.querySelectorAll('.fade-in'); | |
| fadeElements.forEach(element => { | |
| ScrollTrigger.create({ | |
| trigger: element, | |
| start: "top 80%", | |
| onEnter: () => element.classList.add('active'), | |
| once: true | |
| }); | |
| }); | |
| // Process Steps Animation | |
| const processSteps = document.querySelectorAll('.process-step'); | |
| let currentStep = 0; | |
| function highlightStep() { | |
| processSteps.forEach(step => step.classList.remove('active')); | |
| processSteps[currentStep].classList.add('active'); | |
| currentStep = (currentStep + 1) % processSteps.length; | |
| } | |
| // Change step every 3 seconds | |
| setInterval(highlightStep, 3000); | |
| // Initialize Particles.js | |
| particlesJS('particles-js', { | |
| particles: { | |
| number: { | |
| value: 80, | |
| density: { | |
| enable: true, | |
| value_area: 800 | |
| } | |
| }, | |
| color: { | |
| value: "#1E88E5" | |
| }, | |
| shape: { | |
| type: "circle", | |
| }, | |
| opacity: { | |
| value: 0.5, | |
| random: true, | |
| }, | |
| size: { | |
| value: 3, | |
| random: true, | |
| }, | |
| line_linked: { | |
| enable: true, | |
| distance: 150, | |
| color: "#0F9D58", | |
| opacity: 0.4, | |
| width: 1 | |
| }, | |
| move: { | |
| enable: true, | |
| speed: 2, | |
| direction: "none", | |
| random: true, | |
| straight: false, | |
| out_mode: "out", | |
| bounce: false, | |
| } | |
| }, | |
| interactivity: { | |
| detect_on: "canvas", | |
| events: { | |
| onhover: { | |
| enable: true, | |
| mode: "grab" | |
| }, | |
| onclick: { | |
| enable: true, | |
| mode: "push" | |
| }, | |
| resize: true | |
| }, | |
| modes: { | |
| grab: { | |
| distance: 140, | |
| line_linked: { | |
| opacity: 1 | |
| } | |
| }, | |
| push: { | |
| particles_nb: 4 | |
| } | |
| } | |
| }, | |
| retina_detect: true | |
| }); | |
| // Initialize Three.js Electrolyzer Visualization | |
| initElectrolyzerAnimation(); | |
| }); | |
| // Three.js Electrolyzer Animation | |
| function initElectrolyzerAnimation() { | |
| const canvas = document.getElementById('electrolyzer-canvas'); | |
| // Scene, camera, renderer | |
| const scene = new THREE.Scene(); | |
| scene.background = new THREE.Color(0xf9f9f9); | |
| const camera = new THREE.PerspectiveCamera(75, canvas.clientWidth / canvas.clientHeight, 0.1, 1000); | |
| camera.position.z = 5; | |
| const renderer = new THREE.WebGLRenderer({ canvas: canvas, antialias: true }); | |
| renderer.setSize(canvas.clientWidth, canvas.clientHeight); | |
| // Electrolyzer components | |
| const electrolyzerGroup = new THREE.Group(); | |
| // Main cylinder | |
| const cylinderGeometry = new THREE.CylinderGeometry(1, 1, 3, 32); | |
| const cylinderMaterial = new THREE.MeshPhongMaterial({ | |
| color: 0x888888, | |
| transparent: true, | |
| opacity: 0.8, | |
| specular: 0x111111, | |
| shininess: 100 | |
| }); | |
| const cylinder = new THREE.Mesh(cylinderGeometry, cylinderMaterial); | |
| electrolyzerGroup.add(cylinder); | |
| // Electrodes | |
| const electrodeGeometry = new THREE.BoxGeometry(0.1, 2.5, 0.5); | |
| const anodeMaterial = new THREE.MeshPhongMaterial({ color: 0x1E88E5 }); | |
| const cathodeMaterial = new THREE.MeshPhongMaterial({ color: 0x0F9D58 }); | |
| const anode = new THREE.Mesh(electrodeGeometry, anodeMaterial); | |
| anode.position.x = -0.4; | |
| electrolyzerGroup.add(anode); | |
| const cathode = new THREE.Mesh(electrodeGeometry, cathodeMaterial); | |
| cathode.position.x = 0.4; | |
| electrolyzerGroup.add(cathode); | |
| // Water particles | |
| const particles = new THREE.Group(); | |
| const particleGeometry = new THREE.SphereGeometry(0.03, 8, 8); | |
| const particleMaterial = new THREE.MeshBasicMaterial({ color: 0x00bfff }); | |
| for (let i = 0; i < 50; i++) { | |
| const particle = new THREE.Mesh(particleGeometry, particleMaterial); | |
| particle.position.x = (Math.random() - 0.5) * 1.5; | |
| particle.position.y = (Math.random() - 0.5) * 2.5; | |
| particle.position.z = (Math.random() - 0.5) * 1.5; | |
| particle.userData = { | |
| speed: Math.random() * 0.01 + 0.005, | |
| direction: Math.random() > 0.5 ? 1 : -1 | |
| }; | |
| particles.add(particle); | |
| } | |
| electrolyzerGroup.add(particles); | |
| // Hydrogen and Oxygen bubbles | |
| const bubbles = new THREE.Group(); | |
| const hydrogenMaterial = new THREE.MeshBasicMaterial({ color: 0x88ff88 }); | |
| const oxygenMaterial = new THREE.MeshBasicMaterial({ color: 0xff8888 }); | |
| for (let i = 0; i < 30; i++) { | |
| const bubbleMaterial = i % 2 === 0 ? hydrogenMaterial : oxygenMaterial; | |
| const size = i % 2 === 0 ? 0.04 : 0.02; // hydrogen is bigger | |
| const bubbleGeometry = new THREE.SphereGeometry(size, 8, 8); | |
| const bubble = new THREE.Mesh(bubbleGeometry, bubbleMaterial); | |
| // Position to either side | |
| const side = i % 2 === 0 ? 0.4 : -0.4; | |
| bubble.position.x = side + (Math.random() - 0.5) * 0.3; | |
| bubble.position.y = (Math.random() - 0.5) * 2.5; | |
| bubble.position.z = (Math.random() - 0.5) * 0.5; | |
| bubble.userData = { | |
| speed: Math.random() * 0.015 + 0.005, | |
| wiggle: Math.random() * 0.01, | |
| phaseOffset: Math.random() * Math.PI * 2 | |
| }; | |
| bubbles.add(bubble); | |
| } | |
| electrolyzerGroup.add(bubbles); | |
| // Add to scene | |
| scene.add(electrolyzerGroup); | |
| // Lighting | |
| const ambientLight = new THREE.AmbientLight(0xffffff, 0.5); | |
| scene.add(ambientLight); | |
| const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8); | |
| directionalLight.position.set(5, 5, 5); | |
| scene.add(directionalLight); | |
| const backLight = new THREE.DirectionalLight(0xffffff, 0.3); | |
| backLight.position.set(-5, 5, -5); | |
| scene.add(backLight); | |
| // Animation | |
| function animate() { | |
| requestAnimationFrame(animate); | |
| // Rotate electrolyzer | |
| electrolyzerGroup.rotation.y += 0.005; | |
| // Animate water particles | |
| particles.children.forEach(particle => { | |
| particle.position.y += particle.userData.speed * particle.userData.direction; | |
| if (particle.position.y > 1.5 || particle.position.y < -1.5) { | |
| particle.userData.direction *= -1; | |
| } | |
| }); | |
| // Animate bubbles | |
| bubbles.children.forEach(bubble => { | |
| bubble.position.y += bubble.userData.speed; | |
| bubble.position.x += Math.sin(Date.now() * 0.001 + bubble.userData.phaseOffset) * bubble.userData.wiggle; | |
| if (bubble.position.y > 1.5) { | |
| bubble.position.y = -1.5; | |
| bubble.position.x = (bubble.position.x > 0 ? 0.4 : -0.4) + (Math.random() - 0.5) * 0.3; | |
| } | |
| }); | |
| renderer.render(scene, camera); | |
| } | |
| // Handle resize | |
| window.addEventListener('resize', () => { | |
| camera.aspect = canvas.clientWidth / canvas.clientHeight; | |
| camera.updateProjectionMatrix(); | |
| renderer.setSize(canvas.clientWidth, canvas.clientHeight); | |
| }); | |
| animate(); | |
| } | |
| </script> | |
| </body> | |
| </html> | |