animated_text_effects 0.0.7
animated_text_effects: ^0.0.7 copied to clipboard
A Flutter package with 66 composable text animation effects, sequence widgets, and 4 animated counter widgets.
animated_text_effects #
A Flutter package for text with 66 composable animation effects and 4 animated counter widgets. Combine effects freely, control playback, and persist state across scroll off-screen.
✨ Features #
- 66 effects — fade, wave, typewriter, fire, smoke, matrix rain, glitch, scramble, shake, tracking, glow reveal, kinetic type, split reveal, ink drops, chromatic aberration, pixelate, water ripple, vortex, cascade, origami, shatter, morph, curtain, stomp, typewriter error, typewriter delete, falling leaves, fireflies, breath, circular reveal, scan lines, bar wake, weight, countdown, and more
- Composable — apply multiple effects simultaneously (opacity multiplies, translation sums, last color wins)
- Loop modes — forward, ping-pong, or finite repeat counts
- External controller —
TextEffectControllerfor play/pause/stop/seek - Scroll persistence — animations survive scrolling off-screen via
keepAlive(defaulttrue) - Counter widgets —
AnimatedCounter,AnimatedPercentage,AnimatedCurrency,AnimatedStatCard,RollingDigitCounter - Sequence widgets —
AnimatedTextSequencefor sequential multi-text playback,AnimatedRichTextfor mixing static & animated text inline - Interactive demos — included in example app with real-time parameter controls
📋 Effects #
📂 Entry & Reveal #
Fade #
AnimatedText(
'Hello World',
effects: const [FadeEffect()],
style: TextStyle(fontSize: 32),
)
Slide #
AnimatedText(
'Hello World',
effects: const [SlideEffect()],
style: TextStyle(fontSize: 32),
)
Blur #
AnimatedText(
'Hello World',
effects: const [BlurEffect()],
style: TextStyle(fontSize: 32),
)
Typewriter #
AnimatedText(
'Hello World',
effects: const [TypewriterEffect()],
style: TextStyle(fontSize: 32),
)
Scatter #
AnimatedText(
'Hello World',
effects: const [ScatterEffect()],
style: TextStyle(fontSize: 32),
)
Staggered Appear #
AnimatedText(
'Hello World',
effects: const [StaggeredAppearEffect()],
style: TextStyle(fontSize: 32),
)
Random Reveal #
AnimatedText(
'Hello World',
effects: const [RandomRevealEffect()],
style: TextStyle(fontSize: 32),
)
Reveal #
AnimatedText(
'Hello World',
effects: const [RevealEffect()],
style: TextStyle(fontSize: 32),
)
Scramble #
AnimatedText(
'Hello World',
effects: const [ScrambleEffect()],
style: TextStyle(fontSize: 32),
)
Pop In #
AnimatedText(
'Hello World',
effects: const [PopInEffect()],
style: TextStyle(fontSize: 32),
)
Ripple #
AnimatedText(
'Hello World',
effects: const [RippleEffect()],
style: TextStyle(fontSize: 32),
)
Elastic #
AnimatedText(
'Hello World',
effects: const [ElasticEffect()],
style: TextStyle(fontSize: 32),
)
🎯 Motion & Energy #
Wave #
AnimatedText(
'Hello World',
effects: const [WaveEffect()],
style: TextStyle(fontSize: 32),
)
Bounce #
AnimatedText(
'Hello World',
effects: const [BounceEffect()],
style: TextStyle(fontSize: 32),
)
Wiggle #
AnimatedText(
'Hello World',
effects: const [WiggleEffect()],
style: TextStyle(fontSize: 32),
)
Shake #
AnimatedText(
'Hello World',
effects: const [ShakeEffect()],
style: TextStyle(fontSize: 32),
)
Pulse #
AnimatedText(
'Hello World',
effects: const [PulseEffect()],
style: TextStyle(fontSize: 32),
)
Spin #
AnimatedText(
'Hello World',
effects: const [SpinEffect()],
style: TextStyle(fontSize: 32),
)
Flip #
AnimatedText(
'Hello World',
effects: const [FlipEffect()],
style: TextStyle(fontSize: 32),
)
Flag Wave #
AnimatedText(
'Hello World',
effects: const [FlagWaveEffect()],
style: TextStyle(fontSize: 32),
)
Liquid #
AnimatedText(
'Hello World',
effects: const [LiquidEffect()],
style: TextStyle(fontSize: 32),
)
Conveyor Belt #
AnimatedText(
'Hello World',
effects: const [ConveyorBeltEffect()],
style: TextStyle(fontSize: 32),
)
🌈 Color & Light #
Gradient #
AnimatedText(
'Hello World',
effects: const [GradientEffect()],
style: TextStyle(fontSize: 32),
)
Rainbow #
AnimatedText(
'Hello World',
effects: const [RainbowEffect()],
style: TextStyle(fontSize: 32),
)
Glow #
AnimatedText(
'Hello World',
effects: const [GlowEffect()],
style: TextStyle(fontSize: 32),
)
Shimmer #
AnimatedText(
'Hello World',
effects: const [ShimmerEffect()],
style: TextStyle(fontSize: 32),
)
Wave Color #
AnimatedText(
'Hello World',
effects: const [WaveColorEffect()],
style: TextStyle(fontSize: 32),
)
Breathing Opacity #
AnimatedText(
'Hello World',
effects: const [BreathingOpacityEffect()],
style: TextStyle(fontSize: 32),
)
Glow Reveal #
AnimatedText(
'Hello World',
effects: const [GlowRevealEffect()],
style: TextStyle(fontSize: 32),
)
Neon Flicker #
AnimatedText(
'Hello World',
effects: const [NeonFlickerEffect()],
style: TextStyle(fontSize: 32),
)
Highlight #
AnimatedText(
'Hello World',
effects: const [HighlightEffect()],
style: TextStyle(fontSize: 32),
)
Sparkle Twinkle #
AnimatedText(
'Hello World',
effects: const [SparkleTwinkleEffect()],
style: TextStyle(fontSize: 32),
)
Scanner #
AnimatedText(
'Hello World',
effects: const [ScannerEffect()],
style: TextStyle(fontSize: 32),
)
💥 VFX & Distortion #
Fire #
AnimatedText(
'Hello World',
effects: const [FireEffect()],
style: TextStyle(fontSize: 32),
)
Smoke #
AnimatedText(
'Hello World',
effects: const [SmokeEffect()],
style: TextStyle(fontSize: 32),
)
VHS Glitch #
AnimatedText(
'Hello World',
effects: const [VHSGlitchEffect()],
style: TextStyle(fontSize: 32),
)
Glitch Split #
AnimatedText(
'Hello World',
effects: const [GlitchSplitEffect()],
style: TextStyle(fontSize: 32),
)
Matrix Rain #
AnimatedText(
'Hello World',
effects: const [MatrixRainEffect()],
style: TextStyle(fontSize: 32),
)
Melt Drip #
AnimatedText(
'Hello World',
effects: const [MeltDripEffect()],
style: TextStyle(fontSize: 32),
)
Kinetic Type #
AnimatedText(
'Hello World',
effects: const [KineticTypeEffect()],
style: TextStyle(fontSize: 32),
)
Split Reveal #
AnimatedText(
'Hello World',
effects: const [SplitRevealEffect()],
style: TextStyle(fontSize: 32),
)
Ink Drops #
AnimatedText(
'Hello World',
effects: const [InkDropsEffect()],
style: TextStyle(fontSize: 32),
)
Chromatic Aberration #
AnimatedText(
'Hello World',
effects: const [ChromaticAberrationEffect()],
style: TextStyle(fontSize: 32),
)
Pixelate #
AnimatedText(
'Hello World',
effects: const [PixelateEffect()],
style: TextStyle(fontSize: 32),
)
Water Ripple #
AnimatedText(
'Hello World',
effects: const [WaterRippleEffect()],
style: TextStyle(fontSize: 32),
)
Vortex #
AnimatedText(
'Hello World',
effects: const [VortexEffect()],
style: TextStyle(fontSize: 32),
)
Cascade #
AnimatedText(
'Hello World',
effects: const [CascadeEffect()],
style: TextStyle(fontSize: 32),
)
Origami #
AnimatedText(
'Hello World',
effects: const [OrigamiEffect()],
style: TextStyle(fontSize: 32),
)
Shatter #
AnimatedText(
'Hello World',
effects: const [ShatterEffect()],
style: TextStyle(fontSize: 32),
)
Morph #
AnimatedText(
'Hello World',
effects: const [MorphEffect()],
style: TextStyle(fontSize: 32),
)
Curtain #
AnimatedText(
'Hello World',
effects: const [CurtainEffect()],
style: TextStyle(fontSize: 32),
)
Stomp #
AnimatedText(
'Hello World',
effects: const [StompEffect()],
style: TextStyle(fontSize: 32),
)
Typewriter Error #
AnimatedText(
'Hello World',
effects: const [TypewriterErrorEffect()],
style: TextStyle(fontSize: 32),
)
Typewriter Delete #
AnimatedText(
'Hello World',
effects: const [TypewriterDeleteEffect()],
style: TextStyle(fontSize: 32),
)
Falling Leaves #
AnimatedText(
'Hello World',
effects: const [FallingLeavesEffect()],
style: TextStyle(fontSize: 32),
)
Fireflies #
AnimatedText(
'Hello World',
effects: const [FirefliesEffect()],
style: TextStyle(fontSize: 32),
)
Breath #
AnimatedText(
'Hello World',
effects: const [BreathEffect()],
style: TextStyle(fontSize: 32),
)
Circular Reveal #
AnimatedText(
'Hello World',
effects: const [CircularRevealEffect()],
style: TextStyle(fontSize: 32),
)
Scan Lines #
AnimatedText(
'Hello World',
effects: const [ScanLinesEffect()],
style: TextStyle(fontSize: 32),
)
Bar Wake #
AnimatedText(
'Hello World',
effects: const [BarWakeEffect()],
style: TextStyle(fontSize: 32),
)
Weight #
AnimatedText(
'Hello World',
effects: const [WeightEffect()],
style: TextStyle(fontSize: 32),
)
Countdown #
AnimatedText(
'Hello World',
effects: const [CountdownEffect()],
style: TextStyle(fontSize: 32),
)
📏 Utility #
Progress Text #
AnimatedText(
'Hello World',
effects: const [ProgressTextEffect()],
style: TextStyle(fontSize: 32),
)
Tracking #
AnimatedText(
'Hello World',
effects: const [TrackingEffect()],
style: TextStyle(fontSize: 32),
)
Underline #
AnimatedText(
'Hello World',
effects: const [UnderlineEffect()],
style: TextStyle(fontSize: 32),
)
🔗 Sequence & Rich Text #
AnimatedTextSequence #
AnimatedTextSequence(
texts: [
SequenceText('Hello', effects: const [FadeEffect()]),
SequenceText('World', effects: const [WaveEffect()]),
SequenceText('!', effects: const [BounceEffect()]),
],
repeat: true,
displayDuration: Duration(seconds: 2),
transitionDuration: Duration(milliseconds: 600),
style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold),
)
AnimatedRichText #
AnimatedRichText(
segments: [
TextSegment.static('Static '),
TextSegment.animated('Animated!', effects: const [FadeEffect(), WaveEffect()]),
TextSegment.static(' suffix'),
],
repeat: true,
style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold),
)
AnimatedCounter #
AnimatedCounter(
value: 99999,
duration: Duration(seconds: 3),
style: TextStyle(fontSize: 48, fontWeight: FontWeight.bold),
)
AnimatedPercentage #
AnimatedPercentage(
value: 87.5,
decimals: 1,
style: TextStyle(fontSize: 48, fontWeight: FontWeight.bold),
)
AnimatedCurrency #
AnimatedCurrency(
value: 123456.78,
decimals: 2,
symbol: r'$',
style: TextStyle(fontSize: 48, fontWeight: FontWeight.bold),
)
RollingDigitCounter #
RollingDigitCounter(
value: 2026,
style: TextStyle(fontSize: 48, fontWeight: FontWeight.bold),
)
AnimatedStatCard #
AnimatedStatCard(
value: 8472,
label: 'Users',
icon: Icons.people,
activeColor: Colors.blue,
)
🚀 Getting started #
Import #
import 'package:animated_text_effects/animated_text_effects.dart';
📟 Counter widgets reference #
AnimatedCounter #
AnimatedCounter({
required num value,
Duration duration = 1000ms,
Curve curve = easeOut,
TextStyle? style,
int decimals = 0,
Color? activeColor,
bool scalePulse = false,
bool autoplay = true,
bool keepAlive = true,
String Function(num)? format,
})
AnimatedPercentage #
AnimatedPercentage({
required num value,
int decimals = 1,
Duration duration = 1000ms,
Curve curve = easeOut,
TextStyle? style,
bool autoplay = true,
bool keepAlive = true,
Color? activeColor,
bool scalePulse = false,
bool showPercentSign = true,
})
AnimatedCurrency #
AnimatedCurrency({
required num value,
int decimals = 2,
String symbol = r'$',
Duration duration = 1000ms,
Curve curve = easeOut,
TextStyle? style,
bool autoplay = true,
bool keepAlive = true,
Color? activeColor,
bool scalePulse = false,
bool showPlusSign = false,
})
AnimatedStatCard #
AnimatedStatCard({
required num value,
required String label,
IconData? icon,
int decimals = 0,
Duration duration = 1000ms,
Curve curve = easeOut,
TextStyle? valueStyle,
TextStyle? labelStyle,
Color? activeColor,
bool scalePulse = false,
Color? cardColor,
double elevation = 2,
EdgeInsetsGeometry padding = EdgeInsets.all(20),
bool autoplay = true,
String Function(num)? format,
})
RollingDigitCounter #
RollingDigitCounter({
required num value,
int decimals = 0,
Duration duration = 1000ms,
TextStyle? style,
bool autoplay = true,
bool keepAlive = true,
double digitWidth = 28,
double digitHeight = 40,
Color? backgroundColor,
})
🧩 AnimatedText widget API #
| Parameter | Type | Default | Description |
|---|---|---|---|
text |
String |
— | Text to animate |
effects |
List<TextEffect> |
[] |
Effects to apply (order matters for color) |
controller |
TextEffectController? |
null |
External playback control |
style |
TextStyle? |
inherits | Text styling |
autoplay |
bool |
true |
Start animation automatically |
repeat |
bool |
false |
Loop infinitely |
reverse |
bool |
false |
Ping-pong (requires repeat: true) |
textAlign |
TextAlign |
start |
Text alignment |
textDirection |
TextDirection |
ltr |
Text direction |
keepAlive |
bool |
true |
Persist animation in scroll views |
🧩 CharacterAnimation properties #
| Property | Type | Combined as | Description |
|---|---|---|---|
opacity |
double |
Multiplied | Character opacity |
translation |
Offset |
Summed | Displacement from origin |
scale |
double |
Multiplied | Uniform scale |
scaleX |
double |
Multiplied | Horizontal scale |
scaleY |
double |
Multiplied | Vertical scale |
color |
Color? |
Last non-null wins | Text color |
backgroundColor |
Color? |
Last non-null wins | Background behind character |
blurSigma |
double |
Summed | Gaussian blur |
rotation |
double |
Summed | 2D rotation (radians) |
rotationX |
double |
Summed | 3D X rotation (radians) |
rotationY |
double |
Summed | 3D Y rotation (radians) |
underlineProgress |
double |
Summed | Underline fill (0–1) |
clipProgress |
double |
Multiplied | Visible portion (0–1) |
🧪 Composing effects #
| Property | Combination rule |
|---|---|
opacity |
Multiplied across effects |
translation |
Summed across effects |
scale, scaleX, scaleY |
Multiplied across effects |
color, backgroundColor |
Last non-null wins |
blurSigma, rotation, rotationX, rotationY, underlineProgress |
Summed across effects |
clipProgress |
Multiplied across effects |
🧩 Sequence widgets API #
AnimatedTextSequence #
| Parameter | Type | Default | Description |
|---|---|---|---|
texts |
List<SequenceText> |
— | Ordered list of text items to cycle through |
controller |
TextEffectController? |
null |
External playback control |
style |
TextStyle? |
inherits | Text styling (applied to all texts) |
autoplay |
bool |
true |
Start animation automatically |
repeat |
bool |
true |
Loop infinitely through the sequence |
displayDuration |
Duration |
3s |
How long each text is displayed |
transitionDuration |
Duration |
500ms |
Duration of the cross-fade between texts |
transitionEffect |
TextEffect? |
null |
Effect applied during transitions (null = plain cross-fade) |
textAlign |
TextAlign |
start |
Text alignment |
textDirection |
TextDirection |
ltr |
Text direction |
keepAlive |
bool |
true |
Persist animation in scroll views |
SequenceText #
| Parameter | Type | Default | Description |
|---|---|---|---|
text |
String |
— | Text content for this item |
effects |
List<TextEffect> |
[] |
Effects to apply when this text is displayed |
style |
TextStyle? |
null |
Per-item text style override |
segments |
List<TextSegment>? |
null |
Fine-grained segment control (for mixed static/animated within one item) |
AnimatedRichText #
| Parameter | Type | Default | Description |
|---|---|---|---|
segments |
List<TextSegment> |
— | Ordered list of static or animated text segments |
controller |
TextEffectController? |
null |
External playback control |
style |
TextStyle? |
inherits | Base text styling |
autoplay |
bool |
true |
Start animation automatically |
repeat |
bool |
false |
Loop infinitely |
reverse |
bool |
false |
Ping-pong (requires repeat: true) |
textAlign |
TextAlign |
start |
Text alignment |
textDirection |
TextDirection |
ltr |
Text direction |
keepAlive |
bool |
true |
Persist animation in scroll views |
TextSegment #
| Constructor | Parameters | Description |
|---|---|---|
TextSegment.static(text) |
text |
Non-animated text segment |
TextSegment.animated(text, {effects}) |
text, effects |
Animated text segment with optional effects |
📐 Effect contract #
All effects guarantee f(0) == f(1) — at progress=0 and progress=1 every character returns to its base state. This ensures seamless looping and predictable end states.
Noise-based effects (FireEffect, NeonFlickerEffect, VHSGlitchEffect, WiggleEffect, SparkleTwinkleEffect) wrap their output to enforce this contract.
Use noise(int index, [int offset]) on TextEffect for deterministic pseudo-random values per character:
final value = noise(index); // 0.0–1.0 per character
final value = noise(index, 42); // with offset for different noise streams
🔄 Scroll persistence #
Animations survive scrolling off-screen by default (keepAlive: true). This uses AutomaticKeepAliveClientMixin under the hood.
For more advanced persistence across widget mount/unmount (e.g., conditional rendering), use TextEffectController which saves its progress internally on detach and restores on attach:
class MyWidget extends StatefulWidget {
@override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> with SingleTickerProviderStateMixin {
final controller = TextEffectController();
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
if (showText)
AnimatedText(
'Persistent text',
effects: const [FadeEffect(), WaveEffect()],
controller: controller,
),
],
);
}
}
🎮 Interactive demos #
The example app includes two interactive demos reachable from the AppBar:
- Text — multi-effect checkboxes with per-effect parameter sliders (all 45 effects)
- Counters — all 5 counter types with global controls (value, decimals, duration, curve, color, scale pulse) and a reset button that recreates all widgets from scratch
- Sequence — interactive
AnimatedTextSequencewith per-text effect selection and transition effect picker - Comprehensive — tabbed demo (Static Text, Sequence, Mixed) with gap support, per-text effects, color, curve, and font size controls
- Cmp Counters — tabbed counter demo (Single, Dashboard, Mixed) with inline prefix/suffix text mixing
cd example
flutter run
🏗️ Architecture #
lib/
├── animated_text_effects.dart # Barrel exports
├── core/
│ ├── text_effect.dart # Abstract base with noise() helper
│ ├── text_effect_controller.dart # Playback controller with attach/detach
│ ├── character_animation.dart # Per-character animation data
│ ├── animated_text.dart # Main AnimatedText widget
│ ├── text_segment.dart # Static or animated segment for AnimatedRichText
│ ├── sequence_text.dart # Text item with effects for AnimatedTextSequence
│ ├── animated_rich_text.dart # Inline static + animated text segments
│ ├── animated_text_sequence.dart # Sequential multi-text playback with transitions
│ └── animated_counter.dart # AnimatedCounter base widget
├── effects/ # 45 effect implementations
│ ├── fade_effect.dart
│ ├── gradient_effect.dart
│ ├── wave_effect.dart
│ ├── typewriter_effect.dart
│ ├── bounce_effect.dart
│ ├── shimmer_effect.dart
│ ├── slide_effect.dart
│ ├── blur_effect.dart
│ ├── rainbow_effect.dart
│ ├── glow_effect.dart
│ ├── ripple_effect.dart
│ ├── spin_effect.dart
│ ├── flip_effect.dart
│ ├── wiggle_effect.dart
│ ├── pulse_effect.dart
│ ├── scatter_effect.dart
│ ├── neon_flicker_effect.dart
│ ├── elastic_effect.dart
│ ├── highlight_effect.dart
│ ├── underline_effect.dart
│ ├── progress_text_effect.dart
│ ├── staggered_appear_effect.dart
│ ├── fire_effect.dart
│ ├── smoke_effect.dart
│ ├── vhs_glitch_effect.dart
│ ├── reveal_effect.dart
│ ├── liquid_effect.dart
│ ├── scanner_effect.dart
│ ├── wave_color_effect.dart
│ ├── breathing_opacity_effect.dart
│ ├── conveyor_belt_effect.dart
│ ├── melt_drip_effect.dart
│ ├── sparkle_twinkle_effect.dart
│ ├── matrix_rain_effect.dart
│ ├── scramble_effect.dart
│ ├── pop_in_effect.dart
│ ├── shake_effect.dart
│ ├── flag_wave_effect.dart
│ ├── tracking_effect.dart
│ ├── glow_reveal_effect.dart
│ ├── kinetic_type_effect.dart
│ ├── split_reveal_effect.dart
│ ├── ink_drops_effect.dart
│ └── random_reveal_effect.dart
│ └── glitch_split_effect.dart
└── counters/ # Counter widgets
├── animated_percentage.dart
├── animated_currency.dart
├── animated_stat_card.dart
└── rolling_digit_counter.dart
📄 License #
MIT