// modules/canvas-animations/index.js import { Logger } from '../../core/logger.js'; import { CanvasManager } from './CanvasManager.js'; import { ScrollEffects } from './ScrollEffects.js'; import { InteractiveEffects } from './InteractiveEffects.js'; import { DataVisualization } from './DataVisualization.js'; const CanvasAnimationsModule = { name: 'canvas-animations', // Module-level init (called by module system) init(config = {}, state = null) { Logger.info('[CanvasAnimations] Module initialized'); this.initializeCanvasElements(); return this; }, /** * Initialize all canvas elements with data-canvas attributes */ initializeCanvasElements() { // Auto-discover canvas elements const canvasElements = document.querySelectorAll('canvas[data-canvas-type]'); canvasElements.forEach(canvas => { this.initElement(canvas); }); Logger.info(`[CanvasAnimations] Initialized ${canvasElements.length} canvas elements`); }, /** * Initialize individual canvas element */ initElement(canvas, options = {}) { const canvasType = canvas.dataset.canvasType; const canvasConfig = this.parseCanvasConfig(canvas); Logger.info(`[CanvasAnimations] Initializing canvas type: ${canvasType}`); switch (canvasType) { case 'interactive': InteractiveEffects.init(canvas, canvasConfig); break; case 'scroll-parallax': ScrollEffects.initParallax(canvas, canvasConfig); break; case 'scroll-animation': ScrollEffects.initScrollAnimation(canvas, canvasConfig); break; case 'data-viz': DataVisualization.init(canvas, canvasConfig); break; case 'background': this.initBackgroundAnimation(canvas, canvasConfig); break; default: Logger.warn(`[CanvasAnimations] Unknown canvas type: ${canvasType}`); } }, /** * Parse configuration from data attributes */ parseCanvasConfig(canvas) { const config = {}; // Parse all data-canvas-* attributes Object.keys(canvas.dataset).forEach(key => { if (key.startsWith('canvas')) { const configKey = key.replace('canvas', '').toLowerCase(); let value = canvas.dataset[key]; // Try to parse as JSON if it looks like an object/array if ((value.startsWith('{') && value.endsWith('}')) || (value.startsWith('[') && value.endsWith(']'))) { try { value = JSON.parse(value); } catch (e) { Logger.warn(`[CanvasAnimations] Failed to parse JSON config: ${key}`, e); } } // Parse boolean strings else if (value === 'true') value = true; else if (value === 'false') value = false; // Parse numbers else if (!isNaN(value) && value !== '') { value = parseFloat(value); } config[configKey] = value; } }); return config; }, /** * Initialize background animation */ initBackgroundAnimation(canvas, config) { const manager = new CanvasManager(canvas); // Default background animation: floating particles const particleCount = config.particles || 50; const particles = []; // Create particles for (let i = 0; i < particleCount; i++) { particles.push({ x: Math.random() * canvas.width, y: Math.random() * canvas.height, vx: (Math.random() - 0.5) * 0.5, vy: (Math.random() - 0.5) * 0.5, size: Math.random() * 3 + 1, opacity: Math.random() * 0.5 + 0.2 }); } // Animation loop function animate() { manager.clear(); manager.ctx.fillStyle = config.color || 'rgba(100, 150, 255, 0.6)'; particles.forEach(particle => { particle.x += particle.vx; particle.y += particle.vy; // Wrap around edges if (particle.x < 0) particle.x = canvas.width; if (particle.x > canvas.width) particle.x = 0; if (particle.y < 0) particle.y = canvas.height; if (particle.y > canvas.height) particle.y = 0; // Draw particle manager.ctx.save(); manager.ctx.globalAlpha = particle.opacity; manager.ctx.beginPath(); manager.ctx.arc(particle.x, particle.y, particle.size, 0, Math.PI * 2); manager.ctx.fill(); manager.ctx.restore(); }); requestAnimationFrame(animate); } animate(); } }; // Export für module system export const init = CanvasAnimationsModule.init.bind(CanvasAnimationsModule); export default CanvasAnimationsModule;