import React, { useRef, useEffect, useCallback, useMemo } from 'react';
import {
starryNight, floatingBubbles,
gradientWave, particleNetwork, galaxySpiral,
rainbowWaves, geometricShapes, fireflies,
matrixRain, quantumField, electricStorm,
cosmicDust, neonPulse, auroraBorealis, oceanWaves,
neuralNetwork,
dnaHelix, snowFall, realisticRain, autumnLeaves, realisticClouds, fireflyForest, fallingFoodFiesta,
hauntedForest,
ghostlyApparitions,
spiderwebOverlay,
undeadGraveyard,
bloodRain,
creepyCrawlies,
} from './backgroundAnimations';
import AnimatedText from './AnimatedText';
import LayeredBackground from './LayeredBackground';
// Import new features
import { useAnimationControls } from './hooks/useAnimationControls';
import { usePerformanceMonitor } from './hooks/usePerformanceMonitor';
import { createInteractionHandler, GestureRecognizer } from './utils/interactionUtils';
import { ThemeManager, themeManager, COLOR_SCHEMES, THEMES } from './utils/themeSystem';
/**
* @fileoverview Animated Backgrounds v2.0 - Main entry point
* @module AnimatedBackgrounds
* @version 2.0.0
*/
/**
* @typedef {Object} InteractionConfig
* @property {'attract'|'repel'|'follow'|'burst'|'gravity'} [effect='attract'] - Type of interaction effect
* @property {number} [strength=0.5] - Interaction strength (0.1 to 2.0)
* @property {number} [radius=100] - Interaction radius in pixels
* @property {boolean} [continuous=true] - Whether interaction continues after mouse leaves
* @property {boolean} [multiTouch=false] - Enable multi-touch support for mobile
* @example
* // Basic interaction configuration
* const interactionConfig = {
* effect: 'attract',
* strength: 0.8,
* radius: 150,
* continuous: true
* };
*
* // Mobile-optimized configuration
* const mobileConfig = {
* effect: 'follow',
* strength: 0.6,
* radius: 100,
* multiTouch: true
* };
*/
/**
* @typedef {Object} AnimationControls
* @property {boolean} isPlaying - Whether animation is currently playing
* @property {number} speed - Current animation speed multiplier
* @property {Function} play - Start/resume animation
* @property {Function} pause - Pause animation
* @property {Function} reset - Reset animation to initial state
* @property {Function} setSpeed - Set animation speed (0.1x to 5.0x)
* @property {Function} toggle - Toggle play/pause state
*/
/**
* Main AnimatedBackground component that renders stunning animated backgrounds
* with support for themes, interactions, performance monitoring, and controls.
*
* @component
* @param {Object} props - Component props
* @param {string} [props.animationName='geometricShapes'] - Name of the animation to display
* @param {string} [props.fallbackAnimation='geometricShapes'] - Fallback animation if main animation fails
* @param {number} [props.fps=60] - Target frames per second
* @param {string} [props.blendMode='normal'] - Canvas blend mode for visual effects
* @param {Object} [props.style] - Inline styles for the canvas element
* @param {boolean} [props.interactive=false] - Enable mouse/touch interactions
* @param {InteractionConfig} [props.interactionConfig={}] - Configuration for interactions
* @param {string} [props.theme] - Theme name to apply predefined color schemes
* @param {string} [props.preset] - Preset configuration name
* @param {AnimationControls} [props.animationControls] - External animation controls
* @param {boolean} [props.enablePerformanceMonitoring=false] - Enable real-time performance tracking
* @param {boolean} [props.adaptivePerformance=false] - Auto-optimize based on device performance
* @param {string} [props.className] - Additional CSS classes
*
* @returns {JSX.Element} Animated background canvas element
*
* @example
* // Basic usage
* <AnimatedBackground animationName="starryNight" />
*
* @example
* // With theme and interactivity
* <AnimatedBackground
* animationName="particleNetwork"
* theme="gaming"
* interactive={true}
* interactionConfig={{
* effect: 'attract',
* strength: 0.8,
* radius: 150
* }}
* />
*
* @example
* // With performance monitoring and controls
* function App() {
* const controls = useAnimationControls();
*
* return (
* <AnimatedBackground
* animationName="matrixRain"
* theme="cyberpunk"
* animationControls={controls}
* enablePerformanceMonitoring={true}
* adaptivePerformance={true}
* />
* );
* }
*
* @example
* // Mobile-optimized setup
* <AnimatedBackground
* animationName="floatingBubbles"
* theme="wellness"
* interactive={true}
* interactionConfig={{
* effect: 'follow',
* strength: 0.6,
* multiTouch: true
* }}
* adaptivePerformance={true}
* fps={30}
* />
*
* @since 1.0.0
* @version 2.0.0
*/
const AnimatedBackground = React.memo(({
animationName,
fallbackAnimation = 'geometricShapes',
fps = 60,
blendMode = 'normal',
style,
interactive = false,
interactionConfig = {},
theme,
preset,
animationControls,
enablePerformanceMonitoring = false,
adaptivePerformance = false
}) => {
const canvasRef = useRef(null);
const animationRef = useRef(null);
const interactionHandlerRef = useRef(null);
// Initialize performance monitoring if enabled
const performanceMonitor = enablePerformanceMonitoring ? usePerformanceMonitor() : null;
// Apply theme if specified
useEffect(() => {
if (theme) {
themeManager.applyTheme(theme);
}
}, [theme]);
const blendModes = [
'normal',
'multiply',
'screen',
'overlay',
'darken',
'lighten',
'color-dodge',
'color-burn',
'hard-light',
'soft-light',
'difference',
'exclusion',
'hue',
'saturation',
'color',
'luminosity'
];
// Memoize animations object to prevent recreation
const animations = useMemo(() => ({
starryNight, floatingBubbles, gradientWave, particleNetwork, galaxySpiral,
rainbowWaves, geometricShapes, fireflies, matrixRain, quantumField,
electricStorm, cosmicDust, neonPulse, auroraBorealis, oceanWaves,
neuralNetwork, dnaHelix, snowFall, realisticRain, realisticClouds,
fireflyForest, autumnLeaves, fallingFoodFiesta, hauntedForest,
ghostlyApparitions,
spiderwebOverlay,
undeadGraveyard,
bloodRain,
creepyCrawlies,
}), []);
const setupCanvas = useCallback(() => {
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Set blend mode
ctx.globalCompositeOperation = blendModes.includes(blendMode)
? blendMode
: 'normal';
let animation = animations[animationName];
if (!animation) {
console.warn(`Animation "${animationName}" not found. Using fallback animation.`);
animation = animations[fallbackAnimation] || animations.geometricShapes;
}
// Setup interaction handler if interactive mode is enabled
if (interactive && !interactionHandlerRef.current) {
interactionHandlerRef.current = createInteractionHandler(canvas, interactionConfig);
interactionHandlerRef.current.attachListeners();
}
// Get theme-specific settings if available
const themeSettings = theme ? themeManager.getAnimationSettings(animationName) : {};
return animation(canvas, ctx, {
themeManager: theme ? themeManager : null,
interactionHandler: interactionHandlerRef.current,
performanceMonitor,
adaptivePerformance,
...themeSettings
});
}, [animationName, fallbackAnimation, blendMode, interactive, theme, animations]);
// Animation setup effect - only runs when animation or setup changes
useEffect(() => {
const animation = setupCanvas();
let lastTime = 0;
const frameInterval = 1000 / fps;
const loop = (currentTime) => {
// Check animation controls
if (animationControls && !animationControls.isPlaying) {
animationRef.current = requestAnimationFrame(loop);
return;
}
animationRef.current = requestAnimationFrame(loop);
const deltaTime = currentTime - lastTime;
const speedMultiplier = animationControls ? animationControls.speed : 1;
const adjustedFrameInterval = frameInterval / speedMultiplier;
if (deltaTime >= adjustedFrameInterval) {
lastTime = currentTime - (deltaTime % adjustedFrameInterval);
// Record frame for performance monitoring
if (performanceMonitor) {
performanceMonitor.recordFrame();
}
animation();
// Adaptive performance adjustments
if (adaptivePerformance && performanceMonitor) {
const { avgFps, performanceLevel } = performanceMonitor;
if (performanceLevel === 'poor' && avgFps < 20) {
// Automatically reduce complexity or fps
console.warn('Poor performance detected. Consider reducing animation complexity.');
}
}
}
};
animationRef.current = requestAnimationFrame(loop);
return () => {
if (animationRef.current) {
cancelAnimationFrame(animationRef.current);
}
};
}, [setupCanvas, fps, animationControls]); // Removed changing dependencies
// Resize handling effect - separate from animation
useEffect(() => {
const handleResize = () => {
if (canvasRef.current) {
canvasRef.current.width = window.innerWidth;
canvasRef.current.height = window.innerHeight;
setupCanvas();
}
};
window.addEventListener('resize', handleResize);
return () => {
if (interactionHandlerRef.current) {
interactionHandlerRef.current.removeListeners();
}
window.removeEventListener('resize', handleResize);
};
}, [setupCanvas]);
return (
<canvas
ref={canvasRef}
style={{
position: 'fixed',
top: 0,
left: 0,
width: '100%',
height: '100%',
zIndex: -1,
pointerEvents: interactive ? 'auto' : 'none',
...style
}}
/>
);
});
export {
// Main components
AnimatedBackground,
AnimatedText,
LayeredBackground,
// Animation functions
starryNight,
floatingBubbles,
gradientWave,
particleNetwork,
galaxySpiral,
rainbowWaves,
geometricShapes,
fireflies,
matrixRain,
quantumField,
electricStorm,
cosmicDust,
neonPulse,
auroraBorealis,
fallingFoodFiesta,
hauntedForest,
ghostlyApparitions,
spiderwebOverlay,
undeadGraveyard,
bloodRain,
creepyCrawlies,
// New hooks
useAnimationControls,
usePerformanceMonitor,
// Utilities
createInteractionHandler,
GestureRecognizer,
// Theme system
ThemeManager,
themeManager,
COLOR_SCHEMES,
THEMES
};
Source