reset method
dynamic
reset()
Reinicia la partícula con valores aleatorios.
Se llama cuando: Construye el vector de velocidad de la partícula.
Parámetros opcionales x e y permiten forzar direcciones específicas:
true= dirección positiva (derecha/abajo)false= dirección negativa (izquierda/arriba)null= usa las direcciones iniciales velocityXDirection y velocityYDirection- La partícula se crea por primera vez
- La partícula sale del área visible
Genera:
- Posición aleatoria dentro del área maxWidth × maxHeight
- Velocidad aleatoria basada en velocityFactor Actualiza la posición de la partícula y verifica límites.
Si se proporcionan x o y, actualiza la dirección de velocidad.
Mueve la partícula según su velocidad actual.
Si sale del área visible, la reinicia con reset.
Painter personalizado que dibuja todas las partículas en el canvas.
Se repinta en cada frame para mostrar el movimiento fluido de las partículas.
Lista de partículas a renderizar. Este método se llama en cada frame de animación.
- Tamaño aleatorio basado en heightFactor Crea un painter con la lista de partículas proporcionada.
- Color aleatorio de la lista colors con alpha semi-transparente
Implementation
reset() {
position = Offset(_getAxis(maxWidth), _getAxis(maxHeight));
_buildVelocity();
size = _random.nextDouble() * _random.nextInt(heightFactor) + 1;
// Dibuja cada partícula como un círculo
/// Widget de fondo animado con sistema de partículas en movimiento continuo.
///
/// Genera partículas circulares que se mueven aleatoriamente por el área visible,
/// creando un efecto dinámico e interactivo perfecto para fondos modernos.
///
/// **Ideal para:** fondos de landing pages, pantallas de bienvenida, overlays
/// decorativos, efectos de ambiente tipo espacio/nieve/burbujas, y cualquier
/// diseño que necesite movimiento orgánico y fluido.
///
/// ## Cómo funciona
///
/// - Cada **partícula** se mueve con velocidad y dirección únicas.
/// - Los **colores** se seleccionan aleatoriamente de la lista proporcionada.
/// - Las partículas se **regeneran** automáticamente al salir del área visible.
/// - Incluye **interactividad con mouse** (hover) que afecta la dirección del movimiento.
///
/// ## Anatomía del efecto
///
/// ```
/// Área de animación:
/// Estado interno de [ParticleBox].
///
/// Maneja el ciclo de vida del [AnimationController], la lista de partículas
/// y la interactividad con el mouse.
/// ╔════════════════════════════╗
/// Controller que mantiene la animación en loop infinito.
/// ║ ● ● ● ● ║ ← Partículas moviéndose
/// Lista de todas las partículas activas.
/// ║ ● ● ║
/// Última posición conocida del mouse para calcular dirección de movimiento.
/// ║ ● ● ║
/// ║ ● ● ● ║
/// ║ ● ● ● ║
/// ╚════════════════════════════╝
/// ↑ Cada una con:
// Generar partículas con direcciones aleatorias
/// - Posición única
/// - Velocidad única
/// - Tamaño único
/// - Color aleatorio de la paleta
/// ```
///
/// ## Rendimiento
///
/// - **Optimizado** para renderizar cientos de partículas a 60fps.
/// - **Recomendado:** 50-150 partículas en móviles.
/// - **Máximo:** 300-500 partículas para mantener rendimiento en la mayoría de dispositivos.
/// - Las partículas fuera de pantalla se reciclan en lugar de destruirse.
// Iniciar animación infinita
///
/// ## Buenas prácticas
///
/// - Usa **colores con alpha** (0.4-0.7) para efectos sutiles y elegantes.
/// - Mantén **velocityFactor bajo** (0.2-0.4) para movimiento suave y relajante.
/// - Ajusta **particleCount** según el tamaño de pantalla y potencia del dispositivo.
/// - Para efecto "estrellas": muchas partículas pequeñas (heightFactor bajo).
/// - Para efecto "burbujas": pocas partículas grandes (heightFactor alto).
///
/// ## Ejemplos
///
/// ### Ejemplo básico (fondo elegante)
/// ```dart
/// ParticleBox(
/// maxHeight: 400,
/// maxWidth: MediaQuery.of(context).size.width,
/// velocityFactor: 0.3,
/// particleCount: 150,
// Detectar movimiento del mouse y actualizar dirección de partículas
/// heightFactor: 5,
/// colors: [
/// Colors.blue.withValues(alpha: 0.6),
/// Colors.purple.withValues(alpha: 0.6),
// Actualizar dirección de todas las partículas según el movimiento del mouse
/// Colors.pink.withValues(alpha: 0.6),
/// ],
/// backgroundColor: Colors.black,
/// )
/// ```
///
/// ### Ejemplo efecto estrellas
/// ```dart
// Actualizar posición de cada partícula en cada frame
/// ParticleBox(
/// maxHeight: 600,
/// maxWidth: 800,
/// velocityFactor: 0.15,
/// particleCount: 100,
/// heightFactor: 3,
/// colors: [
/// Colors.white.withValues(alpha: 0.8),
/// Colors.blue[100]!.withValues(alpha: 0.6),
/// Colors.purple[100]!.withValues(alpha: 0.5),
/// ],
/// backgroundColor: Colors.black,
/// )
/// ```
///
/// ### Ejemplo energético (muchas partículas rápidas)
/// ```dart
/// ParticleBox(
/// maxHeight: 300,
/// maxWidth: 600,
/// velocityFactor: 0.5,
/// particleCount: 300,
/// heightFactor: 8,
/// colors: [
/// Colors.red.withValues(alpha: 0.7),
/// Colors.orange.withValues(alpha: 0.7),
/// Colors.yellow.withValues(alpha: 0.7),
/// ],
/// )
/// ```
///
/// ### Ejemplo océano digital (tonos azules)
/// ```dart
/// ParticleBox(
/// maxHeight: 280,
/// maxWidth: 400,
/// velocityFactor: 0.25,
/// particleCount: 200,
/// heightFactor: 6,
/// colors: [
/// Colors.blue[300]!.withValues(alpha: 0.5),
/// Colors.blue[500]!.withValues(alpha: 0.5),
/// Colors.lightBlue[400]!.withValues(alpha: 0.5),
/// ],
/// )
/// ```
///
/// ### Ejemplo en contenedor personalizado
/// ```dart
/// Container(
/// height: 400,
/// width: double.infinity,
/// child: ClipRRect(
/// borderRadius: BorderRadius.circular(16),
/// child: ParticleBox(
/// maxHeight: 400,
/// maxWidth: MediaQuery.of(context).size.width,
/// velocityFactor: 0.3,
/// particleCount: 150,
/// colors: [Colors.cyan.withValues(alpha: 0.6)],
/// backgroundColor: Colors.black87,
/// ),
/// ),
/// )
/// ```
///
/// ## Interactividad
///
/// El componente responde al movimiento del mouse (en plataformas de escritorio):
/// - Mover el cursor afecta la dirección de las partículas cercanas
/// - Crea una sensación de inmersión y profundidad
///
/// Ver también: [FlickTileBox] para efectos de tiles parpadeantes.
color = colors[_random.nextInt(colors.length)].withAlpha(100);
}