layerAnimationProgress function
LayerAnimationProgress?
layerAnimationProgress(
- LayerAnimation animation,
- Duration time, {
- required Duration? start,
- required Duration? end,
The progress of animation at time into the video, or null when it
does not play then.
start and end are the layer's time range (null = the start / the
end of the video): an in-animation plays over the first
LayerAnimation.duration of it and an out-animation over the last. With
AnimationPhase.animateInOut both apply and the one further from rest
wins.
A AnimationPhase.loop plays over the whole range, one cycle per duration
counted from start: the eased value runs from rest to fully away at half
a cycle and back. A wiggle runs that twice per cycle, once to each side
(see LayerAnimationProgress.swing).
Mirrors animationProgress in the native renderer of pro_video_editor,
down to the whole microseconds the cycle position is taken from.
Implementation
LayerAnimationProgress? layerAnimationProgress(
LayerAnimation animation,
Duration time, {
required Duration? start,
required Duration? end,
}) {
final durationUs = animation.duration.inMicroseconds;
if (durationUs <= 0) return null;
final startUs = (start ?? Duration.zero).inMicroseconds;
final curve = animation.curve;
if (animation.phase == AnimationPhase.loop) {
final elapsed = math.max(0, time.inMicroseconds - startUs);
final inCycle = elapsed % durationUs;
if (animation.type == LayerAnimationType.wiggle) {
// Each half of the cycle is one swing out and back.
final inSwing = (2 * inCycle) % durationUs;
final x = (1 - 2 * inSwing / durationUs).abs();
return LayerAnimationProgress(
applyLayerAnimationCurve(curve, x),
swing: 2 * inCycle < durationUs ? 1 : -1,
);
}
final x = (1 - 2 * inCycle / durationUs).abs();
return LayerAnimationProgress(applyLayerAnimationCurve(curve, x));
}
double? inProgress;
double? outProgress;
if (animation.phase == AnimationPhase.animateIn ||
animation.phase == AnimationPhase.animateInOut) {
final elapsed = time.inMicroseconds - startUs;
if (elapsed < durationUs) {
inProgress = applyLayerAnimationCurve(
curve,
(elapsed / durationUs).clamp(0.0, 1.0),
);
}
}
if ((animation.phase == AnimationPhase.animateOut ||
animation.phase == AnimationPhase.animateInOut) &&
end != null) {
final remaining = end.inMicroseconds - time.inMicroseconds;
if (remaining < durationUs) {
outProgress = applyLayerAnimationCurve(
curve,
(remaining / durationUs).clamp(0.0, 1.0),
);
}
}
// The animation further from rest wins.
if (inProgress != null && outProgress != null) {
return LayerAnimationProgress(math.min(inProgress, outProgress));
}
final progress = inProgress ?? outProgress;
return progress == null ? null : LayerAnimationProgress(progress);
}