flutter_effect_system 0.2.0
flutter_effect_system: ^0.2.0 copied to clipboard
A lightweight declarative effect system for Flutter (shake, flash, ripple, particle).
flutter_effect_system #
Lightweight declarative effect system for Flutter — particle, shake, flash, ripple and composition.
Why this package exists
Flutter widgets are great, but games and interactive UIs often need small, composable visual effects that sit between UI and game loops.
This package provides a minimal, allocation-conscious, frame-driven effect orchestration layer (no external game loop or physics engine).
API aims to feel like Unity/Unreal effects but remain fully Flutter-native and declarative.
Core ideas
-
Effect: stateless small units that are applied frame-by-frame with a normalized progress t ∈ [0,1].
-
EffectContext: a tiny accumulator (offset, opacity, overlay painters) provided every frame into which effects push their visual requests.
-
EffectLayer: wraps any widget and composes multiple effects, using a Ticker (manual progression) and a small Stopwatch-based timebase.
-
EffectController: runtime trigger to play effects imperatively.
Key built-in effects (MVP)
-
ShakeEffect — randomized offset jitter with ease-out decay.
-
FlashEffect — fullscreen color overlay with blend mode support.
-
RippleEffect — center-based expanding circle with opacity falloff.
-
ParticleEffect — MVP particle burst (deterministic RNG, velocity + lifetime) drawn via overlay painter.
Quick usage
import 'package:flutter/material.dart';
import 'package:flutter_effect_system/flutter_effect_system.dart';
final controller = EffectController();
EffectLayer(
controller: controller,
effects: [ShakeEffect(intensity: 6, duration: Duration(milliseconds: 300))],
child: MyWidget(),
);
// trigger at runtime
controller.play(ShakeEffect(intensity: 12));
controller.play(FlashEffect(color: Colors.white, duration: Duration(milliseconds: 120)));
controller.play(RippleEffect(center: Offset(0.5,0.5)));
controller.play(ParticleEffect(count: 30));
Run the example
- Get packages
flutter pub get
- Run the example app
# from package root
flutter run -t example/main.dart
Notes on design and performance
-
No AnimationController is used — a Ticker + Stopwatch drives frames to minimize coupling and keep the API small.
-
Effects are stateless and should avoid allocating on the hot path; EffectContext is reused per frame.
-
RepaintBoundary is used to limit repaint scope; overlay painters are batched and drawn into a dedicated repaint boundary.
Next steps (ideas)
-
Add more built-in effects (trail, beam, soft-particle via shaders).
-
Add widget tests validating the
EffectController.playbehavior and that overlay painters are registered. -
Expose more configuration and utility effects (combinators, easing helpers, keyed stacking behavior).
License
MIT — feel free to adapt and publish to pub.dev.
Performance
Particle rendering can be heavy if many effects are stacked. A per-effect
global cap is provided that limits the number of particles generated by each
ParticleEffect instance:
// default is 200
ParticleEffect.globalParticleCap = 80; // reduce for low-end devices
This is a simple, explicit knob—if you need cross-effect coordinated
budgeting we can add a central budget managed by EffectLayer in a follow-up.
A new Flutter project.
Getting Started #
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
For help getting started with Flutter development, view the online documentation, which offers tutorials, samples, guidance on mobile development, and a full API reference.