IconMorphPlan class

Recipe for a IconicMorph — how the source glyph becomes the target.

The choreography the user feels — a travelling "worm", not a cross-fade:

  1. One real line of the SOURCE is the hero — e.g. the user's shoulders arc, picked by sourceAnchor. The worm rests on it.
  2. Its head launches along the line's own tangent and flies a smooth quintic-Hermite curve (flightLaunch, flightLand, flightBow, flightBias) over to the entry of a real TARGET line — e.g. the face's smile, picked by heroAnchor — arriving along the target's tangent so it eases in, never cutting across.
  3. The worm slides onto the target, the tail catching up (headLead) and drawing the smile on. Mechanically: a fixed-length window slides by arc length along one master path (source → flight → target).
  4. Meanwhile the source's other contours (the head ring) leave — by default they un-draw / retract (MorphExit.trim) rather than fade — and the target's others (brackets, eyes, nose) draw on (MorphAssemble — trim / scale / 3D flip), assembling the new icon around the line that travelled.

Everything is a tunable here so the SAME engine drives any pair of icons. This is pure data — the geometry it produces lives in MorphGeometry, the painting in IconicMorphPainter.

Annotations

Constructors

IconMorphPlan({Duration duration = IconMotion.iconMorph, Curve curve = IconicEase.flight, int samples = 200, Offset? heroAnchor, int? heroTargetIndex, Offset? sourceAnchor = const Offset(12, 20), int? sourceIndex, double flightLaunch = 1.5, double flightLand = 1.5, double flightBow = -0.40, double flightBias = 0.5, double flightRunway = 2.0, double headLead = 2.2, double headFade = 0.45, double flipStart = 0.55, double flipStagger = 0.1, double exitTaper = 0.5, double exitFade = 0.75, double assembleFade = 0.35, double taperFloor = 1, double assembleTaper = 0.18, double perspective = 0.0028, MorphAssemble assemble = MorphAssemble.trim, MorphExit exit = MorphExit.trim, bool flipSource = false, bool flipTarget = false})
const

Properties

assemble → MorphAssemble
How the ARRIVING (target) non-hero contours assemble — MorphAssemble.trim (draw-on, the default), MorphAssemble.scale (zoom in), or MorphAssemble.flip3d (the 3D flip). Governs the NEW glyph only.
final
assembleFade → double
Emergence span (0..1) — the share of an arriving contour's own draw over which its ALPHA ramps from nothing to full. The mirror of exitFade.
final
assembleTaper → double
Nib press-down (0..1) — the fraction of an arriving contour's draw-on (MorphAssemble.trim) over which its stroke weight ramps from taperFloor up to full, the mirror of exitTaper. Like it, inert unless taperFloor is lowered below 1. Default 0.18.
final
curve → Curve
The worm's temporal ease — the velocity profile the head and tail ride along the master path. Defaults to IconicEase.flight (peak velocity at the first frame, long soft settle — the signature). Direction-aware: a reverse play mirrors it so the worm still launches fast and lands slow going backward. Swap in IconicEase.snap for a spring launch or any Curve of your own.
final
duration → Duration
Total play time. Prefer IconMotion constants for consistent timing.
final
exit → MorphExit
How the LEAVING (source) non-hero contours disappear — MorphExit.trim (un-draw / retract, the default), MorphExit.fade (alpha fade), or MorphExit.scale (shrink + fade). Governs the OLD glyph only, independent of assemble.
final
exitFade → double
Dissolve span (0..1) — a leaving contour's ALPHA fades to nothing over the last 1 - exitFade of the whole animation. This is the whole vanish. Default 0.75 = a quarter of the morph, ≈160 ms at the default duration.
final
exitTaper → double
Pen-lift taper (0..1) — the point in a leaving contour's exit after which its STROKE WEIGHT starts easing down toward taperFloor.
final
flightBias → double
Bow position — where along the flight the flightBow hump peaks (0..1; 0.5 = mid). Shift toward 0 to fatten the launch side, toward 1 the landing.
final
flightBow → double
Lateral bow — signed swing perpendicular to the head→entry chord, as a fraction of the gap (≈ -0.8…0.8; 0 = no swing). When the two tangents near-oppose, a straight flight has to reverse hard through the middle (the "sharp turn"); a bow swings the whole path wide to ONE side instead, turning that reversal into a single broad arc. Sign picks the side (CW vs CCW); you own the magnitude so it never balloons. Added as a bump that's flat at both ends, so it never disturbs the launch/landing tangents.
final
flightLand → double
Landing breathing — the quintic landing-velocity as a fraction of the gap (≈0.15–0.9). Higher = it eases IN more gradually onto the target tangent (a longer, gentler touchdown). Split from flightLaunch so take-off and landing can breathe independently.
final
flightLaunch → double
Launch breathing — the quintic launch-velocity as a fraction of the head→entry gap (≈0.15–0.9). Higher = the flight eases OUT more gradually off the source tangent (a longer, gentler take-off runway).
final
flightRunway → double
Runway — a STRAIGHT breathing segment (viewBox units, e.g. ~20 at a 24 viewBox) along the tangent at EACH end before the curve is allowed to bend. The launch leaves dead-straight for this far, then curves; the landing arrives dead-straight for the last stretch. 0 = the curve bends immediately off the tangent (no straight runway). Clamped to ≤ 45% of the head→entry gap.
final
flipSource → bool
Reverse the resolved SOURCE hero line (swap its head/tail) AFTER the default "head on the right" orientation — so the worm launches from the other end of the source line. Use per-direction when the default end reads wrong.
final
flipStagger → double
Per-contour flip-in delay (auto-normalized to the contour count).
final
flipStart → double
When the target's non-hero contours start flipping in (0..1).
final
flipTarget → bool
Reverse the resolved TARGET hero line (swap entry/head) AFTER the default "entry on the left" orientation — so the worm lands lying the other way.
final
hashCode → int
The hash code for this object.
no setteroverride
headFade → double
Window 0..headFade over which the source's non-hero contours LEAVE as the morph runs — it caps whichever exit choreography is active (un-draw, fade, or shrink), NOT just a fade. Default 0.45; the trim un-draw then caps at 0.35 and fade/scale at 0.18, so a smaller headFade tightens the active exit.
final
headLead → double
How much the worm's head leads its tail in time (>1). 1 = head and tail move together (it slides rigidly); higher = the head launches ahead and the tail catches up, so the worm stretches out over the flight and draws the target on as the tail lands.
final
heroAnchor → Offset?
Viewbox-space point used to pick the hero TARGET contour: the contour whose centroid is nearest this anchor becomes the morph's destination line — e.g. Offset(12, 16) for a mouth. Order-independent, so it's the robust selector.
final
heroTargetIndex → int?
Explicit hero target contour index — wins over heroAnchor when set.
final
perspective → double
3D perspective strength for the flip-in (used only when assemble is MorphAssemble.flip3d; see Projector3D).
final
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited
samples → int
Points the hero source + target lines are each resampled to. More = a smoother morph at a little more cost. >= 2.
final
sourceAnchor → Offset?
Viewbox-space point used to pick the hero SOURCE contour — the line that morphs into the target. Defaults to the glyph's lower edge Offset(12, 20), e.g. the user's shoulders arc.
final
sourceIndex → int?
Explicit hero source contour index — wins over sourceAnchor when set.
final
taperFloor → double
Ink floor (0..1) — how thin a taper may ever take the stroke, at either end. Default 1: stroke weight is never touched.
final

Methods

copyWith({Duration? duration, Curve? curve, int? samples, Offset? heroAnchor, int? heroTargetIndex, Offset? sourceAnchor, int? sourceIndex, double? flightLaunch, double? flightLand, double? flightBow, double? flightBias, double? flightRunway, double? headLead, double? headFade, double? flipStart, double? flipStagger, double? exitTaper, double? exitFade, double? assembleFade, double? taperFloor, double? assembleTaper, double? perspective, MorphAssemble? assemble, MorphExit? exit, bool? flipSource, bool? flipTarget}) → IconMorphPlan
Returns a copy with selected fields overridden. Useful for tuning a base plan without mutating it — e.g. a slider can override flightBow while keeping all other fields from the original.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
resolveHeroTarget(List<IconContour> targets) → int
Which target contour the source morphs INTO.
resolveSource(List<IconContour> sources) → int
Which source contour is the one that morphs (the rest fade out).
toString() → String
A string representation of this object.
inherited

Operators

operator ==(Object other) → bool
The equality operator.
override