Animation
DrawingSession exposes two independent animation APIs: viewport transitions move the camera, while path effects decorate resolved connectors. Both are transient presentation state. Neither changes route geometry, enters undo history, or becomes part of the serialized document.
All command methods below require a mounted DrawingCanvas; a detached or disposed session throws StateError.
Viewport transitions
dart
Future<bool> animateToPoint(
DiagramPoint point, {
double? zoom,
Duration duration = const Duration(milliseconds: 450),
Curve curve = Curves.easeInOutCubic,
})
Future<bool> animateToRectangle(
DiagramRect bounds, {
double padding = 48,
Duration duration = const Duration(milliseconds: 450),
Curve curve = Curves.easeInOutCubic,
})
Future<bool> animateToElement(
String elementId, {
double padding = 48,
Duration duration = const Duration(milliseconds: 450),
Curve curve = Curves.easeInOutCubic,
})
Future<bool> animateToRegion(
String elementId,
String regionId, {
double padding = 48,
Duration duration = const Duration(milliseconds: 450),
Curve curve = Curves.easeInOutCubic,
})
Future<bool> animateToSelection({
double padding = 48,
Duration duration = const Duration(milliseconds: 450),
Curve curve = Curves.easeInOutCubic,
})| Target method | Required arguments | Target geometry |
|---|---|---|
animateToPoint | point: DiagramPoint. | World center; optional zoom preserves the current scale when omitted. |
animateToRectangle | bounds: DiagramRect. | Fit world bounds to the viewport. |
animateToElement | elementId: String. | Fit the element's resolved bounds. |
animateToRegion | elementId: String, regionId: String. | Fit the declared shape-layer region, transformed into world bounds. |
animateToSelection | None. | Fit the current resolved selection bounds. |
| Optional argument | Type | Default | Behavior |
|---|---|---|---|
zoom | double? | null | Point target only; clamped to camera zoom limits. |
padding | double | 48 | Bounds targets only; logical pixels on each viewport edge. |
duration | Duration | 450 ms | Transition time. Zero or negative durations apply the target immediately. |
curve | Flutter Curve | Curves.easeInOutCubic | Easing for interpolating center and zoom. |
The returned future resolves to true when the transition finishes, including an unchanged target or an immediate transition. It resolves to false when interrupted or when an element, region, or selection cannot be resolved. A missing target returns false without replacing an existing animation. Target geometry is captured when the command starts; this is not a continuous follow-element behavior.
Zoom limits and finite-canvas policy still apply. When system animations are disabled, viewport transitions apply immediately. See Navigation for fitting and region lookup semantics.
dart
final completed = await session.animateToElement(
'approval',
padding: 64,
duration: const Duration(milliseconds: 600),
curve: Curves.easeOutCubic,
);
if (!completed) {
// The target was absent, or navigation interrupted the transition.
}Cancellation
dart
void stopViewportAnimation()Stops at the current camera position and completes an active transition with false. It is safe to call when no transition is running. Starting another valid transition, immediate navigation, and user navigation interrupt the active transition. Unmounting also cancels it. There is no document transaction to undo.
Observe camera changes using addPresentationListener. The transition future describes completion; the listener supplies changing camera snapshots.
Path-effect commands
dart
bool startPathAnimation(DiagramPathAnimation animation)
bool stopPathAnimation(String animationId)
void clearPathAnimations()
Map<String, DiagramPathAnimation> get pathAnimations
DiagramPathEffectRegistry get pathEffects| Member | Arguments | Result and behavior |
|---|---|---|
startPathAnimation | animation: playback definition. | true when admitted; false for invalid values, an unregistered effect kind, or a missing resolved connector. Reuses an existing animation ID to replace its definition. |
stopPathAnimation | animationId: playback ID, not connector ID. | true if removed; false if no playback had that ID. |
clearPathAnimations | None. | Removes every active path effect. |
pathAnimations | None. | Read-only map keyed by animation ID; empty when detached. Reading after disposal throws. |
pathEffects | None. | Registry from DrawingConfiguration.pathEffects. |
Multiple playback IDs may target the same connector. Removing a connector prunes its effects. Effects follow the connector's current resolved route, including rerouting after shape movement. Stopping playback restores the authored base-path paint. Use presentation listeners to observe explicit start, replacement, stop, and clear commands; they are not a per-frame effect clock.
dart
session.startPathAnimation(const DiagramPathAnimation(
id: 'approval-flow',
connectorId: 'review-to-approval',
particle: DiagramDashParticle(),
count: 6,
size: 2,
strokeWidth: 2,
period: Duration(milliseconds: 1800),
basePathOpacity: 0.15,
));
final current = session.pathAnimations['approval-flow'];
if (current != null) {
session.startPathAnimation(current.copyWith(count: 10));
}
session.stopPathAnimation('approval-flow');DiagramPathAnimation
Its constructor uses named arguments. id and connectorId are required; every other property has a default.
| Property | Type | Default | Contract |
|---|---|---|---|
id | String | Required | Nonempty playback identity. |
connectorId | String | Required | Existing resolved connector ID. |
kind | DiagramPathAnimationKind | .particles | Registry key; standard kinds are particles and pulse. |
scaleMode | DiagramPathAnimationScaleMode | .world | world scales dimensions with zoom; screen retains logical-pixel dimensions. |
period | Duration | 1600 ms | Positive loop duration. Smaller values move faster. |
color | DiagramColor? | null | Falls back to connector color. |
endColor | DiagramColor? | null | Optional second gradient color across path bounds. Character particles currently do not render this gradient. |
particle | DiagramParticleVisual | DiagramCircleParticle() | Visual used by the particles effect. |
count | int | 5 | Positive number of evenly distributed particles. |
size | double | 3 | Positive finite particle dimension, interpreted below. |
strokeWidth | double | 2 | Positive finite dash or pulse thickness. |
opacity | double | 0.9 | Effect opacity, from 0 to 1. |
phase | double | 0 | Loop offset, from 0 to 1. |
reverse | bool | false | Reverses progress along the route. |
basePathOpacity | double | 0.2 | Base-line opacity multiplier, from 0 to 1; does not modify authored style. |
isValid performs runtime validation, including in release builds. hasValidPeriod reports whether the period is positive. Constructor assertions are not the only admission check.
copyWith(...) accepts kind, period, color, endColor, clearEndColor, scaleMode, particle, count, size, strokeWidth, opacity, reverse, and basePathOpacity. It retains id, connectorId, and phase; construct a new instance to change these. Passing clearEndColor: true removes the gradient. Passing null for color preserves the old color; there is no clear-color flag.
Particle visuals
| Constructor | Arguments | Size interpretation |
|---|---|---|
DiagramCircleParticle() | None. | Radius = size. |
DiagramDashParticle() | None. | Length = size × 8, limited by total route length; thickness = strokeWidth. |
DiagramPolygonParticle({int sides = 4, double rotation = math.pi / 4}) | sides: 3–20; rotation: finite radians. | Circumradius = size. |
DiagramCharacterParticle(String character) | Exactly one nonblank grapheme cluster, including an emoji. | Rendered character font scale = size × 2. |
Increasing count changes spacing, not particle dimensions. Dense particles can overlap. Dash width and length remain independent. Particles are distributed by resolved path length, not by a raw Bezier parameter.
Pulse draws a periodically fading stroke and wider halo over the entire route. It uses strokeWidth; it does not use particle, count, or size. The inspector advertises effect-specific properties, although the playback model currently carries a shared set of fields.
Custom path effects
dart
final effects = DiagramPathEffectRegistry.withStandard([
DiagramPathEffectDefinition(
kind: const DiagramPathAnimationKind('my-effect'),
label: 'My effect',
properties: {DiagramPathEffectProperty.color},
paint: (canvas, context) {
final paint = context.createPaint()
..style = PaintingStyle.stroke
..strokeWidth = 2 * context.sizeToWorld;
canvas.drawPath(context.path, paint);
},
),
]);
final configuration = DrawingConfiguration(pathEffects: effects);Import Flutter painting types for custom callbacks. The example draws a stroke using the effect color and scaling mode.
| API | Arguments / return | Contract |
|---|---|---|
DiagramPathEffectRegistry(definitions) | Iterable of definitions → registry. | Uses exactly the supplied effects. Rejects empty kinds/labels and duplicate kinds with ArgumentError. |
DiagramPathEffectRegistry.withStandard(custom) | Iterable of definitions → registry. | Adds custom effects to the standard set; duplicate standard kinds are rejected. |
DiagramPathEffectRegistry.standard | Registry. | Built-in particles and pulse. |
definitions | Iterable<DiagramPathEffectDefinition>. | Registered definitions. |
contains(kind) | Kind → bool. | Checks registration. |
require(kind) | Kind → definition. | Throws StateError when missing. |
DiagramPathEffectDefinition
| Constructor argument | Type | Required / default |
|---|---|---|
kind | DiagramPathAnimationKind | Required registry identity. |
label | String | Required inspector label. |
paint | void Function(Canvas, DiagramPathEffectContext) | Required paint callback. |
properties | Set<DiagramPathEffectProperty> | Empty by default; retained as an immutable set. |
Advertised properties are particle, color, gradient, speed, baseOpacity, opacity, size, width, count, direction, and scale. They select inspector controls; the painter defines their actual effect.
DiagramPathEffectContext
| Member | Type | Purpose |
|---|---|---|
connector | ResolvedConnector | Current resolved connector. |
pathGeometry | ResolvedPathGeometry | Authoritative path sampling. |
path | Flutter Path | Copy of the resolved paint path; modifying it does not corrupt retained geometry. |
metric | Flutter PathMetric | Path length and segment extraction. |
animation | DiagramPathAnimation | Playback settings. |
progress | double | Loop progress after phase and direction. |
inverseZoom | double | Inverse current camera scale. |
sizeToWorld | double | 1 for world scaling; inverse zoom for screen scaling. |
createPaint([double intensity = 1]) | Flutter Paint | Applies color, gradient and opacity. Rejects nonfinite intensity or values outside 0..1 with ArgumentError. |
Custom effect paint runs in world space against current route geometry. Keep it paint-only; document changes belong in session/store commands.