PhysicsControllerMulti class
A controller for multi-dimensional physics-based animations that supports both standard curves and physics simulations.
Similar to PhysicsController, but works with multiple dimensions to control animations in N-dimensional space using lists of values. Key features include:
- Accepts both standard Curves and PhysicsSimulations (like Spring)
- Dynamically responds to changes mid-animation when using physics simulations
- Maintains velocity across animation updates
- Drop-in replacement for AnimationController in multi-dimensional contexts
Usage
Create a controller with a TickerProvider (usually from SingleTickerProviderStateMixin):
class _MyWidgetState extends State<MyWidget> with SingleTickerProviderStateMixin {
late final _controller = PhysicsControllerMulti(
dimensions: 3, // For 3D space
vsync: this,
defaultPhysics: [
Spring.elegant, // X-axis physics
Spring.swift, // Y-axis physics
Spring.gentle, // Z-axis physics
],
);
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
Using with Standard Curves
When using standard curves, you must provide a duration either in the constructor or in animation methods:
// In constructor
final controller = PhysicsControllerMulti(
dimensions: 2,
vsync: this,
duration: const Duration(milliseconds: 300),
defaultPhysics: [
Curves.easeOut,
Curves.easeIn,
],
);
// Or in methods
controller.animateTo(
[100.0, 200.0],
duration: const Duration(milliseconds: 300),
physics: [
Curves.easeOut,
Curves.easeIn,
],
);
Using with Physics Simulations
{@tool snippet} Physics simulations like Spring automatically calculate their duration and respond naturally to interruptions:
class PhysicsObject extends StatefulWidget {
const PhysicsObject({super.key});
@override
State<PhysicsObject> createState() => _PhysicsObjectState();
}
class _PhysicsObjectState extends State<PhysicsObject>
with SingleTickerProviderStateMixin {
late final _controller = PhysicsControllerMulti.unbounded(
dimensions: 3,
vsync: this,
defaultPhysics: [
Spring.elegant,
Spring.elegant,
Spring.elegant,
],
);
List<double> _position = [0, 0, 0];
void _onUpdate(List<double> delta) {
for (int i = 0; i < _position.length; i++) {
_position[i] += delta[i];
}
_controller.animateTo(_position);
}
void _onEnd(List<double> velocity) {
// Physics simulation maintains momentum
_controller.animateTo(
List.filled(3, 0),
velocityDelta: velocity,
);
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Transform.translate(
offset: Offset(_controller.value[0], _controller.value[1]),
child: Transform.translate(
offset: Offset(0, _controller.value[2]),
child: child,
),
);
},
child: const Card(
child: FlutterLogo(size: 128),
),
);
}
}
{@end-tool}
Responding to Changes Mid-Animation
Physics simulations maintain momentum when target values change:
// Initial animation
controller.animateTo([100, 100, 100]);
// Later, interrupt with new target
await Future.delayed(const Duration(milliseconds: 100));
controller.animateTo([50, 50, 50]); // Maintains current velocity
Common Use Cases
- Multi-dimensional animations (3D, 4D, etc.)
- Complex physics simulations
- Particle systems
- Data visualization animations
This controller can be used anywhere AnimationController is accepted, with the values accessible as a list.
See also:
- PhysicsController2D, for 2D-specific animations
- Spring, a physics simulation that creates natural-feeling animations
- PhysicsController, the 1D version of this controller
- AnimationController, Flutter's standard animation controller
- Inheritance
-
- Object
- Listenable
- Animation<
UnmodifiableListView< double> > - PhysicsControllerMulti
- Mixed-in types
Constructors
-
PhysicsControllerMulti.new({required int dimensions, List<
double> ? value, String? debugLabel, required TickerProvider vsync, AnimationBehavior animationBehavior = AnimationBehavior.normal, List<Physics> ? defaultPhysics, Physics? defaultPhysicsForAllDimensions, List<double> ? lowerBound, List<double> ? upperBound, Duration? duration, Duration? reverseDuration}) -
PhysicsControllerMulti.unbounded({required int dimensions, List<
double> ? value, String? debugLabel, required TickerProvider vsync, AnimationBehavior animationBehavior = AnimationBehavior.normal, List<Physics> ? defaultPhysics, Physics? defaultPhysicsForAllDimensions, List<double> ? lowerBound, List<double> ? upperBound, Duration? duration, Duration? reverseDuration}) - Creates an unbounded 2D physics-based animation controller.
Properties
- animationBehavior → AnimationBehavior
-
The behavior of the controller when animations are disabled via
AccessibilityFeatures.disableAnimations.
final
- debugLabel → String?
-
A label that is used in the toString output. Useful for debugging.
final
-
defaultPhysics
↔ List<
Physics> -
Sets the default physics simulation for each dimension.
getter/setter pair
- dimensions → int
-
The number of dimensions this controller animates.
For example, 3 for 3D space, 4 for 4D space, etc.
final
- duration ↔ Duration?
-
The duration of the animation when using non-physics-based animations.
getter/setter pair
- hashCode → int
-
The hash code for this object.
no setterinherited
- isAnimating → bool
-
Whether this animation is currently running in either direction.
no setteroverride
- isCompleted → bool
-
Whether this animation is stopped at the end.
no setterinherited
- isDismissed → bool
-
Whether this animation is stopped at the beginning.
no setterinherited
- isForwardOrCompleted → bool
-
Whether the current aim of the animation is toward completion.
no setterinherited
- lastElapsedDuration → Duration?
-
The time elapsed since the animation started.
no setter
-
lowerBound
→ UnmodifiableListView<
double> -
The lower bounds for each dimension.
final
- reverseDuration ↔ Duration?
-
The duration of the animation when reversing with non-physics-based animations.
getter/setter pair
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
- status → AnimationStatus
-
The current status of this animation.
no setteroverride
-
upperBound
→ UnmodifiableListView<
double> -
The upper bounds for each dimension.
final
-
value
↔ UnmodifiableListView<
double> -
The current position of the animation in N-dimensional space.
getter/setter pairoverride-getter
-
velocity
→ UnmodifiableListView<
double> -
The current velocity of the animation in points per second.
no setter
Methods
-
addListener(
VoidCallback listener) → void -
Calls the listener every time the value of the animation changes.
inherited
-
addStatusListener(
AnimationStatusListener listener) → void -
Calls listener every time the status of the animation changes.
inherited
-
animateTo(
List< double> target, {Duration? duration, List<Physics> ? physics, List<double> ? velocityDelta, List<double> ? velocityOverride}) → TickerFuture -
Drives the animation from its current position to
target
. -
animateWith(
List< Simulation> simulations) → TickerFuture - Drives the animation according to the given 2D simulation.
-
clearListeners(
) → void -
Removes all listeners added with addListener.
inherited
-
clearStatusListeners(
) → void -
Removes all listeners added with addStatusListener.
inherited
-
didRegisterListener(
) → void -
This implementation ignores listener registrations.
inherited
-
didUnregisterListener(
) → void -
This implementation ignores listener registrations.
inherited
-
dimension(
int dimension) → Animation< double> - Returns an Animation<double> that tracks a single dimension of this controller.
-
dispose(
) → void -
Release the resources used by this object.
override
-
drive<
U> (Animatable< U> child) → Animation<U> -
Chains a Tween (or CurveTween) to this Animation.
inherited
-
forward(
{List< double> ? from}) → TickerFuture -
Starts the animation from the current position (or
from
) to upperBound. -
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
notifyListeners(
) → void -
Calls all the listeners.
inherited
-
notifyStatusListeners(
AnimationStatus status) → void -
Calls all the status listeners.
inherited
-
removeListener(
VoidCallback listener) → void -
Stop calling the listener every time the value of the animation changes.
inherited
-
removeStatusListener(
AnimationStatusListener listener) → void -
Stops calling the listener every time the status of the animation changes.
inherited
-
repeat(
{List< double> ? min, List<double> ? max, bool reverse = false, int? count, List<Physics> ? physics}) → TickerFuture -
Repeats the animation between
min
andmax
forcount
times or indefinitely. -
reset(
) → void - Resets the controller's value to lowerBound, stopping the animation.
-
resync(
TickerProvider vsync) → void - Recreates the Ticker with the new TickerProvider.
-
reverse(
{List< double> ? from}) → TickerFuture -
Starts the animation from the current position (or
from
) to lowerBound. -
stop(
{bool canceled = true}) → UnmodifiableListView< double> - Stops the current animation and returns the velocity at the moment of stopping.
-
toString(
) → String -
A string representation of this object.
inherited
-
toStringDetails(
) → String -
Provides a string describing the status of this object, but not including
information about the object itself.
override
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited