ui_animations_pro 0.1.0 copy "ui_animations_pro: ^0.1.0" to clipboard
ui_animations_pro: ^0.1.0 copied to clipboard

ui_animations_pro — production-grade cinematic UI Animations framework for Flutter. Plugin-based Transitions, Composable Choreographer, Timeline Sequencer, Spring Physics Engine, Performance Monitor, [...]

ui_animations_pro #

Production-grade cinematic UI animations for Flutter.
Plugin-based Transitions · Composable Choreographer · Timeline Sequencer · Spring Physics Engine · Frame Budgeter · Accessibility-aware · Reactive Streams · Zero native dependencies.

pub version Flutter Dart License: MIT


🎬 Motion Demo Release #

Download the full showcase application:

Includes:

  • Full cinematic animation showcase
  • Transition playground
  • Physics simulation demos
  • Route transition examples
  • Gesture-driven motion examples
  • Accessibility & reduce-motion previews
  • Performance monitor overlay
  • Adaptive quality demonstrations

Why ui_animations_pro? #

Before After
Manual AnimationController + Tween + Curve per widget Declarative Scene DSL — 5 lines
dispose() management in every State Pool-managed tickers — automatic cleanup
Synchronising N animations via callback hell Choreographer orchestrates everything
No FPS monitoring or adaptive quality FrameBudgeter + PerformanceMonitor built-in
Accessibility left as an afterthought ReduceMotionPolicy + AccessibilityBridge always-on
Custom transition = rewrite from scratch Register a TransitionPlugin — one file

Architecture #

┌──────────────────────────────────────────────────────┐
│                 FLUTTER APPLICATION                    │
│                                                        │
│   AnimationsPro.instance                              │
│     .scene('checkout')                                │
│     .stagger([                                        │
│        SingleStep(id:'logo',  transition: Fade()),    │
│        SingleStep(id:'title', transition: SlideUp()), │
│        SingleStep(id:'cta',   transition: Spring()),  │
│     ], interval: 80ms)                                │
│     .play()                                           │
└────────────────────┬─────────────────────────────────┘
                     ▼
   ┌─────────────────────────────────────────────────┐
   │             PUBLIC API (AnimationsPro)           │
   └────────────────────┬────────────────────────────┘
                        ▼
   ┌─────────────────────────────────────────────────┐
   │   CHOREOGRAPHY LAYER (Scene · Timeline · Steps) │
   └────────────────────┬────────────────────────────┘
                        ▼
   ┌─────────────────────────────────────────────────┐
   │   TRANSITION LAYER (12 Plugin-based effects)    │
   └────────────────────┬────────────────────────────┘
                        ▼
   ┌─────────────────────────────────────────────────┐
   │   CURVES & PHYSICS (Spring · Friction · Bezier) │
   └────────────────────┬────────────────────────────┘
                        ▼
   ┌─────────────────────────────────────────────────┐
   │   ENGINE (FrameBudgeter · Pool · Lifecycle)     │
   └─────────────────────────────────────────────────┘

Installation #

dependencies:
  ui_animations_pro: ^0.1.0
flutter pub get

Quick start #

1. Initialise once in main() #

import 'package:ui_animations_pro/ui_animations_pro.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await AnimationsPro.initialize(
    config: const AnimationsConfig(
      defaultDurationMs: 350,
      respectReduceMotion: true,
      enablePerformanceMonitor: true,
      debug: true,
    ),
  );
  runApp(const MyApp());
}
@override
Widget build(BuildContext context) {
  return ReduceMotionPolicy(
    behavior: ReduceMotionBehavior.crossFade,
    child: MotionProvider(
      child: MaterialApp(home: const HomeScreen()),
    ),
  );
}

3. Play a choreographed scene #

import 'package:ui_animations_pro/transitions.dart';

final handle = AnimationsPro.instance
  .scene('onboarding')
  .stagger([
    SingleStep(id: 'logo',  transition: FadeTransitionPlugin()),
    SingleStep(id: 'title', transition: SlideTransitionPlugin(),
               params: {'direction': SlideDirection.up}),
    SingleStep(id: 'cta',   transition: SpringTransitionPlugin()),
  ], interval: const Duration(milliseconds: 80))
  .play();

// Control
handle.pause();
handle.resume();
handle.seek(0.5);   // jump to 50%
handle.cancel();
await handle.dispose();

Core concepts #

Scene — immutable, composable #

Every .stagger, .sequence, .parallel, .then returns a new Scene.
The original is never mutated — enabling temporal debugging and replay.

final scene = AnimationsPro.instance
  .scene('checkout')
  .sequence([step1, step2])        // sequential
  .parallel([step3, step4])        // simultaneous
  .stagger([step5, step6, step7],  // staggered
      interval: const Duration(milliseconds: 60))
  .delay(const Duration(milliseconds: 200))
  .then(step8);

Choreography steps #

Step Description
SingleStep One transition on one target
SequenceStep Steps play one after another
ParallelStep Steps play simultaneously
StaggerStep Steps start with progressive delay
DelayStep Silent pause in the timeline
LoopStep Repeats infinitely (until cancelled)
RepeatStep Repeats exactly N times
ConditionalStep Runtime branch — if predicate → ifTrue else ifFalse

MotionHandle — full playback control #

final handle = AnimationsPro.instance.playScene(myScene);

handle.state;       // MotionState enum
handle.progress;    // 0.0 → 1.0
handle.events;      // Stream<AnimationEvent>

handle.pause();
handle.resume();
handle.seek(0.75);
handle.cancel();
await handle.dispose();

AnimationEvent stream #

AnimationsPro.instance.events.listen((event) {
  switch (event) {
    case SceneStartedEvent():   print('Started: ${event.sceneId}');
    case SceneCompletedEvent(): print('Done in ${event.totalDuration}');
    case ScenePausedEvent():    print('Paused at ${event.progress}');
    case FrameDropEvent():      print('Frame drop: ${event.frameMs}ms');
  }
});

Transition Plugins (12 built-in) #

Import package:ui_animations_pro/transitions.dart.

Plugin id Expensive
FadeTransitionPlugin fade No
SlideTransitionPlugin slide No
ScaleTransitionPlugin scale No
RotateTransitionPlugin rotate No
SpringTransitionPlugin spring No
Flip3DTransitionPlugin flip3d No
MorphTransitionPlugin morph No
ParallaxTransitionPlugin parallax No
ShimmerTransitionPlugin shimmer No
BlurTransitionPlugin blur Yes
RippleTransitionPlugin ripple Yes
LiquidTransitionPlugin liquid Yes

Using a plugin directly on a widget #

MotionWidget(
  transition: SpringTransitionPlugin(),
  duration: const Duration(milliseconds: 600),
  curve: CurveLibrary.appleSpring,
  child: MyCard(),
)

Writing a custom plugin #

class GlowPlugin implements TransitionPlugin {
  @override String get id => 'glow';
  @override bool get isExpensive => false;
  @override List<AnimatableProperty> get affectedProperties =>
      [AnimatableProperty.opacity];

  @override
  Widget build({
    required Animation<double> animation,
    required Widget child,
    Map<String, Object?> params = const {},
  }) {
    return AnimatedBuilder(
      animation: animation,
      builder: (_, c) => DecoratedBox(
        decoration: BoxDecoration(
          boxShadow: [
            BoxShadow(
              color: Colors.amber.withOpacity(animation.value),
              blurRadius: 24 * animation.value,
              spreadRadius: 4 * animation.value,
            ),
          ],
        ),
        child: c,
      ),
      child: child,
    );
  }
}

// Register globally
AnimationsPro.instance.registerTransition(GlowPlugin());

Curves #

CurveLibrary presets #

CurveLibrary.appleSpring        // Apple-like spring
CurveLibrary.emphasized         // Material 3 emphasized
CurveLibrary.emphasizedDecelerate
CurveLibrary.emphasizedAccelerate
CurveLibrary.overshoot          // Overshoots target then settles
CurveLibrary.anticipate         // Pulls back before moving
CurveLibrary.stripe             // Stripe.com style
CurveLibrary.linearFlow         // Smooth ease
CurveLibrary.elasticOut
CurveLibrary.bounceOut
CurveLibrary.smoothStartEnd

SpringCurve — physics-based #

SpringCurve.gentle()    // stiffness: 120, damping: 14
SpringCurve.wobbly()    // stiffness: 180, damping: 12
SpringCurve.stiff()     // stiffness: 210, damping: 20
SpringCurve.slow()      // stiffness: 280, damping: 60
SpringCurve.molasses()  // stiffness: 280, damping: 120

// or fully custom:
SpringCurve(stiffness: 160, damping: 16, mass: 1.0)

BezierEditor — CSS curves in Dart #

// From code:
final curve = BezierEditor(x1: 0.25, y1: 0.1, x2: 0.25, y2: 1.0).build();

// From CSS string:
final curve = BezierEditor.fromCss('cubic-bezier(0.4, 0.0, 0.2, 1.0)');

Physics simulators #

Import package:ui_animations_pro/physics.dart.

// Spring — mass-spring-damper
final sim = SpringSim(from: 0.0, to: 1.0, stiffness: 180, damping: 12);
sim.position(0.5); // position at t=0.5s
sim.velocity(0.5); // velocity at t=0.5s
sim.isDone(2.0);   // has it settled?

// Friction — exponential deceleration
final friction = FrictionSim(position0: 0.0, velocity0: 800.0, drag: 0.135);

// Gravity — uniform acceleration
final gravity = GravitySim(position0: 0.0, velocity0: 0.0, acceleration: 9.81);

// Magnetic — inverse-square attraction / snap
final magnet = MagneticSim(position0: 0.0, target: 100.0, strength: 50.0);

Widgets #

StaggerList — animated list #

StaggerList(
  transition: SpringTransitionPlugin(),
  interval: const Duration(milliseconds: 60),
  itemDuration: const Duration(milliseconds: 400),
  children: myItems.map((item) => ItemCard(item)).toList(),
)

ShimmerBox — skeleton loading #

// Wrap any widget:
ShimmerBox(
  enabled: isLoading,
  child: MyContentWidget(),
)

// Quick rect placeholder:
ShimmerBox.rect(width: 200, height: 16, borderRadius: 8)

RevealWidget — clip-path reveal #

RevealWidget(
  reveal: _isVisible,
  direction: RevealDirection.radial,   // left, right, top, bottom, center, radial
  duration: const Duration(milliseconds: 600),
  curve: CurveLibrary.appleSpring,
  onRevealed: () => print('Revealed!'),
  child: HeroCard(),
)

MorphContainer — shape morphing #

MorphContainer(
  expanded: _isExpanded,
  collapsedDecoration: BoxDecoration(
    color: Colors.blue, borderRadius: BorderRadius.circular(12)),
  expandedDecoration: BoxDecoration(
    color: Colors.white, borderRadius: BorderRadius.circular(28)),
  collapsedSize: const Size(56, 56),
  expandedSize: const Size(double.infinity, 300),
  duration: const Duration(milliseconds: 450),
  curve: CurveLibrary.appleSpring,
  child: myContent,
)

HeroMotion — enhanced Hero #

HeroMotion(
  tag: 'product-image-42',
  curve: CurveLibrary.appleSpring,
  fadeDuring: true,
  scaleToFit: true,
  child: ProductImage(),
)

ParallaxView — depth layers #

// Scroll-driven:
ParallaxView(
  scrollController: _ctrl,
  maxDisplacement: 60.0,
  layers: [
    (child: BackgroundImage(), depth: 0.2),
    (child: MidgroundShapes(), depth: 0.5),
    (child: ForegroundText(), depth: 1.0),
  ],
)

// Pointer-driven (set imperatively):
ParallaxView(
  offset: _pointerOffset,
  layers: [ ... ],
)

Animated Routes #

// Fade through
Navigator.push(context, FadeThroughRoute(page: const DetailPage()));

// Shared axis
Navigator.push(context, SharedAxisRoute(page: const DetailPage(), axis: SharedAxis.x));

// Container transform (scale)
Navigator.push(context, ContainerTransformRoute(page: const DetailPage()));

// Any custom transition:
Navigator.push(context, MotionPageRoute(
  page: const DetailPage(),
  transition: Flip3DTransitionPlugin(),
  duration: const Duration(milliseconds: 700),
  curve: CurveLibrary.appleSpring,
));

// Via RouteAdapter:
final route = RouteAdapter.push(context, DetailPage(), transition: SpringTransitionPlugin());
Navigator.push(context, route);

Gestures #

// Drag → progress
GestureMotion(
  maxDrag: 300.0,
  axis: Axis.vertical,
  onRelease: (progress) => print('Released at $progress'),
  builder: (ctx, progress) => MyDraggable(progress: progress),
)

// Swipe to dismiss
SwipeDismiss(
  threshold: 0.4,
  onDismissed: () => removeItem(),
  child: MyListTile(),
)

// Pinch to zoom
PinchZoomMotion(minScale: 1.0, maxScale: 4.0, child: MyImage())

// Mouse/touch parallax
PanParallax(strength: 20.0, child: MyCard())

Accessibility #

ui_animations_pro is WCAG 2.1 AA compliant out of the box.

// Policy at app root (detects OS "reduce motion" automatically)
ReduceMotionPolicy(
  behavior: ReduceMotionBehavior.crossFade, // disable | crossFade | scaleDuration | ignore
  durationScale: 0.2,                       // used with scaleDuration
  child: MaterialApp(...),
)

// Semantic wrapper
AccessibilityBridge(
  label: 'Loading indicator',
  hint: 'Content is loading',
  liveRegion: true,
  child: ShimmerBox(enabled: true, child: placeholder),
)

// Announce animation milestones to screen readers
AnimationAnnouncer(
  animation: _controller,
  onStartMessage: 'Menu opening',
  onCompleteMessage: 'Menu opened',
  child: AnimatedMenu(),
)

// Resolve duration against policy
MotionAwareBuilder(
  baseDuration: const Duration(milliseconds: 500),
  builder: (ctx, policy, resolved) {
    return MotionWidget(duration: resolved, transition: ..., child: ...);
  },
)

Performance #

FrameBudgeter #

Automatically monitors every frame. On 120 Hz devices it targets 8.33 ms; on 60 Hz — 16.67 ms.

// Access diagnostics
print(AnimationsPro.instance.diagnostics);
// {
//   activeScenes: 3,
//   currentFps: '58.2',
//   droppedFrames: 2,
//   isLowPerformance: false,
//   ...
// }

// Live FPS stream
AnimationsPro.instance.fpsStream.listen((fps) {
  // Update an in-app debug overlay
});

Adaptive quality #

Mark expensive plugins with isExpensive = true. When FPS drops below AnimationsConfig.minFpsThreshold (default 50 fps), a host app can conditionally switch:

MotionWidget(
  transition: AnimationsPro.instance.isLowPerformanceDevice
      ? FadeTransitionPlugin()      // lightweight fallback
      : BlurTransitionPlugin(),     // full quality
  child: myWidget,
)

MotionEngine — headless testing #

final engine = MotionEngine();

// Sample timeline at specific timestamps (no Flutter UI required)
final values = engine.sampleAt(myScene, 250 /* ms */);
print(values['logo-step']); // 0.83

// Sample physics simulation
final positions = engine.samplePhysics(
  SpringSim(from: 0, to: 1, stiffness: 180, damping: 12),
  durationSec: 2.0,
  sampleHz: 60,
);

Integration — ThemeBridge #

final bridge = ThemeBridge.of(context);

MotionWidget(
  duration: bridge.mediumDuration,    // 300ms
  curve:    bridge.emphasizedCurve,   // Material 3 emphasized
  child: MyCard(),
)

// Derived shimmer colours matching your theme
ShimmerBox(
  baseColor:      bridge.shimmerBase,
  highlightColor: bridge.shimmerHighlight,
  child: placeholder,
)

// Stagger offset helpers
for (int i = 0; i < items.length; i++) {
  Future.delayed(bridge.staggerOffset(i), () => showItem(i));
}

AnimationsConfig reference #

AnimationsConfig(
  defaultDurationMs: 300,       // Default transition duration
  defaultStaggerMs: 50,         // Default stagger interval
  frameBudgetMs: 16.67,         // 60fps target (use 8.33 for 120fps)
  adaptiveQuality: true,        // Auto-degrade on slow devices
  respectReduceMotion: true,    // Honour OS reduce-motion flag
  enablePerformanceMonitor: true,
  minFpsThreshold: 50,          // Below this → low-performance mode
  allowExpensiveEffects: true,  // Blur, shadow, ripple
  physicsTicksPerSecond: 120,
  physicsRestVelocity: 0.001,
  debug: false,                 // Enable debug overlays
  scenePrefix: 'scene_',        // Namespace for registered scenes
  tickerPoolSize: 16,           // AnimationController pool size
  pauseOnAppBackground: true,   // Auto-pause when app is backgrounded
  precompileTimelines: true,    // Cache compiled timelines
)

Project structure #

ui_animations_pro/
├── lib/
│   ├── ui_animations_pro.dart   ← Main barrel
│   ├── transitions.dart         ← Transition plugins barrel
│   ├── physics.dart             ← Physics simulators barrel
│   └── src/
│       ├── core/                ← Facade, config, exceptions, handle, state
│       ├── choreography/        ← Scene, Timeline, Choreographer, 8 steps
│       ├── transitions/         ← TransitionPlugin + 12 plugins
│       ├── curves/              ← CurveLibrary, Spring, Elastic, Back, Bezier
│       ├── physics/             ← Spring, Friction, Gravity, Magnetic
│       ├── engine/              ← MotionEngine, FrameBudgeter, Pool, Scheduler
│       ├── widgets/             ← MotionWidget, StaggerList, ShimmerBox …
│       ├── routes/              ← Animated page routes
│       ├── gestures/            ← GestureMotion, SwipeDismiss, PinchZoom …
│       ├── accessibility/       ← ReduceMotionPolicy, Bridge, Announcer
│       └── integration/         ← MotionProvider, Observer, ThemeBridge
├── example/motion_demo/         ← Full showcase app
├── test/
│   ├── unit/                    ← Pure Dart unit tests
│   ├── widget/                  ← Flutter widget tests
│   └── integration/             ← End-to-end scene playback tests
├── pubspec.yaml
├── README.md
└── CHANGELOG.md

Running the tests #

flutter test

Run with coverage:

flutter test --coverage
genhtml coverage/lcov.info -o coverage/html

Running the example #

cd example/motion_demo
flutter pub get
flutter run

Roadmap #

Phase Version Feature
MVP v0.1 12 Transitions · 8 Steps · 5 Curves · 4 Physics · Choreographer · FrameBudgeter ✅
Code Gen v0.2 build_runner@Scene / @AnimateProperty annotations
Path Animations v0.3 Animate along SVG Path — logos, signatures, stroke progress
Particle System v0.4 Confetti, smoke, stars emitter at 60 fps
Lottie/Rive Bridge v0.5 Import .lottie / .riv as native Scene
Skeleton AutoLoader v0.6 Auto-shimmer matched-shape on loading widgets
Live Timeline Editor v0.7 In-app drag-and-drop editor → export Dart code
Web Motion Exporter v0.8 Export Scene as CSS animations / WAAPI keyframes
Motion Golden Tester v1.0 Pixel-by-pixel animation regression testing

License #

MIT — see LICENSE.


Acknowledgements #

Architecturally consistent with the TIMSoft ecosystem:
timsoftdz_core · timsoft_os · timsoft_rdl_designer · timsoft_rdl_engine · blogger_orm · flutter_chats_ui

Inspired by: Framer Motion · GSAP · Rive · Lottie · React Spring

3
likes
130
points
3
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

ui_animations_pro — production-grade cinematic UI Animations framework for Flutter. Plugin-based Transitions, Composable Choreographer, Timeline Sequencer, Spring Physics Engine, Performance Monitor, Accessibility-aware, Reactive Streams. Zero native dependencies. 100% Dart/Flutter. Web/Desktop/Mobile compatible.

Topics

#animation #flutter #ui #transitions #physics

License

MIT (license)

Dependencies

flutter

More

Packages that depend on ui_animations_pro