ambient_effects_container

English | 简体中文

ambient_effects_container is a generalized Flutter particle effects container focused on creating immersive environmental atmospheres and dynamic backgrounds. It seamlessly wraps any Flutter Widget and takes over the rendering and memory scheduling of all underlying particles, providing an elegant and smooth dynamic background experience.

Previews

Rain Snow
Rain preview Snow preview
Leaf Sakura
Leaf preview Sakura preview

Currently, the container includes a rich variety of high-quality built-in preset effects:

  • RainEffect: Smoothly falling rain streaks
  • SnowEffect: Serene, drifting snow
  • LeafEffect: Concrete falling leaves with flip animations
  • FireflyEffect: Gently wandering, faintly glowing fireflies illuminating the dark ✨
  • PetalEffect: A powerful, generalized falling petal system! Switch between floral types simply by passing a different PetalStyle. It currently features sakura (cherry blossom), rose, white (pure white petals), and the newly added, breathtakingly romantic wisteria, fully equipped with geometrically varying petal slices and gradient mapping 🌺 (Note: If you preferred the previous syntax, we've still retained the standalone SakuraEffect as a convenient shortcut)

It is a highly reusable, premium-grade particle background foundation. It achieves:

  • Complete decoupling of the rendering layer from the business layer, ensuring zero interference with frontend interaction logic.
  • Underlying implementation based on CustomPainter and object pooling technology, avoiding garbage collection (GC) stutters caused by creating numerous objects per frame.
  • Support for seamless wrapping of both full-screen backgrounds and arbitrary local containers, intelligently scaling particle density according to the container's size.

Core Highlights

  • AmbientEffectsContainer: A unified entry point to adapt to various effects with write-once simplicity.
  • Completely Decoupled Petal System: I have entirely separated the physical movements (falling, rotating, swaying) from the static visuals (SVG paths, gradient layers, veins) of the petals. In the future, even if you want to add any custom floral pattern of your own, you only need to append a few lines of PetalShapeSpec data! It's incredibly light on performance and highly playable.
  • PerformanceMode: Built-in low / balanced / high presets to seamlessly balance visual fidelity and device power consumption.
  • EffectRenderStyle: Supports flat, layered (dual-layer parallax), and cinematic (three-layer panoramic) spatial perspective management.
  • Dynamic Playback Control: Supports real-time pausing and resuming of the underlying rendering engine via the enabled property based on page visibility, maximizing battery and performance savings.

Installation

Add the following dependency to your project's pubspec.yaml:

dependencies:
  ambient_effects_container: ^0.1.0

Quick Start

1. Import the package

import 'package:ambient_effects_container/ambient_effects_container.dart';
import 'package:flutter/material.dart';

2. Full-Screen Background

This is the most typical use case, often used for app login screens, splash screens, or meditation guides. (Note: If the foreground contains a Scaffold, be sure to set its background color to transparent (Colors.transparent), otherwise it will obscure the canvas effects behind it.)

class DemoPage extends StatelessWidget {
  const DemoPage({super.key});

  @override
  Widget build(BuildContext context) {
    return AmbientEffectsContainer(
      effect: const RainEffect.medium(),
      performanceMode: PerformanceMode.balanced,
      renderStyle: EffectRenderStyle.layered,
      backgroundColor: const Color(0xFF233545),
      child: Scaffold(
        backgroundColor: Colors.transparent,
        body: const Center(
          child: Text(
            'Rain Scene',
            style: TextStyle(color: Colors.white, fontSize: 24, fontWeight: FontWeight.w700),
          ),
        ),
      ),
    );
  }
}

This snippet declares three core presentation aspects:

  • effect: Determines the actual physical effect to render.
  • performanceMode: The permitted rendering budget for the animation (directly impacting the maximum number of particles on screen).
  • renderStyle: Whether to introduce depth-of-field parallax to create spatial tension between the foreground and background.

3. Immersive Background for Local Cards

The exceptional advantage of AmbientEffectsContainer lies in its ability to perfectly adapt to any localized small area. It actively detects the actual display area and scales down the total number of particles proportionally, ensuring there is no abrupt "crowded particle accumulation" due to a small card size.

AmbientEffectsContainer(
  effect: const SnowEffect.light(),
  performanceMode: PerformanceMode.low,
  renderStyle: EffectRenderStyle.layered,
  backgroundColor: const Color(0x14000000),
  child: Container(
    height: 220,
    padding: const EdgeInsets.all(20),
    alignment: Alignment.centerLeft,
    decoration: BoxDecoration(
      borderRadius: BorderRadius.circular(20),
    ),
    child: const Text('Snow Card', style: TextStyle(color: Colors.white, fontSize: 20)),
  ),
)

Advanced & Tuning Configurations

Pausing or Freezing Animations

If the page is switched to the background, covered by a heavy overlay, or the user turns on the device's "battery-saving mode," you can dynamically pass enabled: false. The container will immediately put the physics engine to sleep, avoiding extra battery drain.

AmbientEffectsContainer(
  effect: const LeafEffect.medium(),
  enabled: false,  // The particle animation is gently frozen at this moment
  child: const Placeholder(),
)

Understanding Intensity Levels

Please note that preset tags like heavy or light do not merely superficially change the "on-screen quantity." To convey natural phenomena accurately (e.g., the difference between a blizzard and a light drizzle), when the intensity increases, presets often simultaneously increase the absolute falling speed and the wind resistance angle.

If you only wish to increase the "visual density" of particles covering the screen without the urgency of a torrential storm, you can explicitly hold back the speed parameter:

AmbientEffectsContainer(
  effect: const SakuraEffect(
    intensity: SakuraIntensity.heavy, // Enable the highest density preset
    speed: 1.0,                       // Force override to normal speed (making it a slow but extremely dense romantic sakura snow)
  ),
  child: const Placeholder(),
)

Mastering the "Firefly" Wander

Unlike rain, snow, and petals that rely on gravity to fall, the brand new FireflyEffect is born to express suspension and vitality. I specifically discarded the gravity constraints for it, exposing two soul-striking properties:

  • wander: Controls the range of random horizontal and vertical wandering of the particles in the air.
  • blinkSpeed: Controls the rhythm of the breathing, faintly flickering glow.

Simply pair it with a dark background, and you can effortlessly render a serene, vibrant, deeply immersive forest atmosphere in the dark.

Do I Need to Manually Lock particleCount?

In most implementation flows, the engine automatically calculates the most elegant total particle capacity based on the following implicit rule: Container Display Area × Performance Tier (PerformanceMode) × Environmental Intensity (Intensity).

It is recommended to manually override the particleCount property only in the following two specialized cases:

  1. Strict Multi-Platform Consistency Alignment: You do not want the visual proportion of quantities to change due to the different physical areas between tablet and smartphone versions.
  2. Extreme Testing Environments: For instance, you are writing a stress-test page that strictly requires exactly 2000 particles running in the scene.

Detailed Parameter Reference

AmbientEffectsContainer

Through the main constructor, you have comprehensive control over the scene architecture:

const AmbientEffectsContainer({
  Key? key,
  // Core
  required AmbientEffectConfig effect,   // Specific configuration of the effects engine
  required Widget child,                 // The foreground UI tree to be nested
  
  // Behavior and Boundaries
  bool enabled = true,                   // Master switch for the rendering engine
  Clip clipBehavior = Clip.hardEdge,     // Trimming method for out-of-bounds container content
  Alignment childAlignment = Alignment.center,
  Color? backgroundColor,                // Background color layered beneath the particles
  
  // Strategy Presets
  PerformanceMode performanceMode = PerformanceMode.balanced,  
  EffectRenderStyle renderStyle = EffectRenderStyle.flat,      
})

EffectRenderStyle (Parallax Depth Style)

  • flat: All particle objects share the same dimension of projection parameters. Best performance, light and clean visuals.
  • layered: The engine automatically divides particles into foreground and background layers by a certain ratio. The background layer, pushed further away, will gradually shrink, feature slight translucence, and move more sluggishly—creating a classically authenticated depth of field ("far is small and slow").
  • cinematic: Further separates into three thicknesses: front, mid, and background. It leverages dramatic depth and speed differentials to construct an immersive blockbuster atmosphere; highly recommended to try this in full-screen mode.

Example Project

The repository includes a highly comprehensive interactive debugging project located in the example/ directory. You can freely switch scenes within this example app, and even slide the value bars to observe real-time feedback on the physics system and frame rate.

cd example
flutter run

Extension Guide

The underlying design of this project is highly decoupled. If you wish to customize a specific set of new objects for your business (e.g., fluttering merchant vouchers, New Year red envelopes, colorful confetti):

  1. Inherit and create a [New]Effect to handle configuration data exposed to the page.
  2. Create a [New]ParticleState to handle physical collisions, angular velocity updates, and lifespan decay.
  3. Implement your exclusive rule-updating Engine and Canvas drawing core Painter.
  4. Mount them into the factory, and then assemble and use them anywhere just like standard modules.

License

MIT