diff --git a/src/Avalonia.Animation/Animation.cs b/src/Avalonia.Animation/Animation.cs
index d7efc69e10..8b5e760455 100644
--- a/src/Avalonia.Animation/Animation.cs
+++ b/src/Avalonia.Animation/Animation.cs
@@ -54,17 +54,12 @@ namespace Avalonia.Animation
/// Describes a delay to be added before the animation starts, and optionally between
/// repeats of the animation if is set.
///
- public TimeSpan Delay { get; set; }
+ public TimeSpan Delay { get; set; } = TimeSpan.Zero;
///
- /// Gets or sets a value indicating whether will be applied between
- /// iterations of the animation.
+ /// Gets or sets the amount of delay time between iterations.
///
- ///
- /// If this property is not set, then will only be applied to the first
- /// iteration of the animation.
- ///
- public bool DelayBetweenIterations { get; set; }
+ public TimeSpan DelayBetweenIterations { get; set; } = TimeSpan.Zero;
private readonly static List<(Func Condition, Type Animator)> Animators = new List<(Func, Type)>
{
diff --git a/src/Avalonia.Animation/AnimationInstance`1.cs b/src/Avalonia.Animation/AnimationInstance`1.cs
index 52cb9e72c0..69b99f7888 100644
--- a/src/Avalonia.Animation/AnimationInstance`1.cs
+++ b/src/Avalonia.Animation/AnimationInstance`1.cs
@@ -15,18 +15,18 @@ namespace Avalonia.Animation
{
private T _lastInterpValue;
private T _firstKFValue;
- private long _repeatCount;
+ private float _iterationCount;
private long _currentIteration;
private bool _isLooping;
private bool _gotFirstKFValue;
- private bool _iterationDelay;
private FillMode _fillMode;
private PlaybackDirection _animationDirection;
private Animator _parent;
private Animatable _targetControl;
private T _neutralValue;
private double _speedRatio;
- private TimeSpan _delay;
+ private TimeSpan _initialDelay;
+ private TimeSpan _iterationDelay;
private TimeSpan _duration;
private Easings.Easing _easeFunc;
private Action _onCompleteAction;
@@ -50,20 +50,20 @@ namespace Avalonia.Animation
_speedRatio = animation.SpeedRatio;
- _delay = animation.Delay;
+ _initialDelay = animation.Delay;
_duration = animation.Duration;
_iterationDelay = animation.DelayBetweenIterations;
switch (animation.RepeatCount.RepeatType)
{
case RepeatType.None:
- _repeatCount = 1;
+ _iterationCount = 1;
break;
case RepeatType.Loop:
- _isLooping = true;
+ _iterationCount = float.PositiveInfinity;
break;
case RepeatType.Repeat:
- _repeatCount = (long)animation.RepeatCount.Value;
+ _iterationCount = animation.RepeatCount.Value;
break;
}
@@ -76,7 +76,7 @@ namespace Avalonia.Animation
protected override void Unsubscribed()
{
- //Animation may have been stopped before it has finished
+ // Animation may have been stopped before it has finished.
ApplyFinalFill();
_timerSubscription?.Dispose();
@@ -138,83 +138,51 @@ namespace Avalonia.Animation
private void InternalStep(TimeSpan time)
{
DoPlayStates();
- var delayEndpoint = _delay;
- var iterationEndpoint = delayEndpoint + _duration;
- var iterationTime = time;
- //determine if time is currently in the first iteration.
- if (time >= TimeSpan.Zero & time <= iterationEndpoint)
- {
- _currentIteration = 1;
- }
- // time is currently the second to nth iteration.
- else if (time > iterationEndpoint)
- {
- // Subtract first iteration to properly get the subsequent iteration time.
- iterationTime -= iterationEndpoint;
-
- // Ignore delays on subsequent iterations if it's not the initial
- // iteration unless _iterationDelay is enabled.
- if (!_iterationDelay & delayEndpoint > TimeSpan.Zero)
- {
- delayEndpoint = TimeSpan.Zero;
- iterationEndpoint = _duration;
- }
+ var indexTime = time.Ticks;
+ var iterDuration = _duration.Ticks * _speedRatio;
+ var iterDelay = _iterationDelay.Ticks * _speedRatio;
+ var initDelay = _initialDelay.Ticks * _speedRatio;
- // Calculate the current iteration number
- _currentIteration = (iterationTime.Ticks / iterationEndpoint.Ticks) + 2;
- }
- else
+ if (indexTime > 0 & indexTime <= initDelay)
{
- return;
+ DoDelay();
}
-
- // Determine if the current iteration should have its normalized time reversed.
- bool isCurIterReverse = _animationDirection == PlaybackDirection.Normal ? false :
- _animationDirection == PlaybackDirection.Alternate ? (_currentIteration % 2 == 0) ? false : true :
- _animationDirection == PlaybackDirection.AlternateReverse ? (_currentIteration % 2 == 0) ? true : false :
- _animationDirection == PlaybackDirection.Reverse ? true : false;
-
- if (!_isLooping)
+ else
{
- var totalTime = _iterationDelay ? _repeatCount * (_duration.Ticks + _delay.Ticks) : _repeatCount * _duration.Ticks + _delay.Ticks;
-
- // Clamp value when animations ends.
- if (time.Ticks >= totalTime)
- {
- var easedTime = _easeFunc.Ease(isCurIterReverse ? 0.0 : 1.0);
- _lastInterpValue = _interpolator(easedTime, _neutralValue);
+ var fullIterationTime = iterDuration + iterDelay;
+ var opsTime = indexTime - initDelay;
+ var playbackTime = opsTime % fullIterationTime;
+ _currentIteration = (long)Math.Floor(opsTime / fullIterationTime);
+
+ if ((_currentIteration + 1) > _iterationCount)
DoComplete();
- return;
- }
- }
- iterationTime = TimeSpan.FromTicks(iterationTime.Ticks % iterationEndpoint.Ticks);
-
- if (delayEndpoint > TimeSpan.Zero & iterationTime < delayEndpoint)
- {
- DoDelay();
- }
- else
- {
- // Offset the delay time
- iterationTime -= delayEndpoint;
- iterationEndpoint -= delayEndpoint;
+ if (playbackTime <= iterDuration)
+ {
+ var normalizedTime = playbackTime / iterDuration;
- // Normalize time
- var interpVal = (double)iterationTime.Ticks / iterationEndpoint.Ticks;
+ bool isCurIterReverse = _animationDirection == PlaybackDirection.Normal ? false :
+ _animationDirection == PlaybackDirection.Alternate ? (_currentIteration % 2 == 0) ? false : true :
+ _animationDirection == PlaybackDirection.AlternateReverse ? (_currentIteration % 2 == 0) ? true : false :
+ _animationDirection == PlaybackDirection.Reverse ? true : false;
- // Check if normalized time needs to be reversed.
- if (isCurIterReverse)
- interpVal = 1 - interpVal;
+ // Check if normalized time needs to be reversed.
+ if (isCurIterReverse)
+ normalizedTime = 1 - normalizedTime;
- // Ease and interpolate
- var easedTime = _easeFunc.Ease(interpVal);
- _lastInterpValue = _interpolator(easedTime, _neutralValue);
+ // Ease and interpolate
+ var easedTime = _easeFunc.Ease(normalizedTime);
+ _lastInterpValue = _interpolator(easedTime, _neutralValue);
- PublishNext(_lastInterpValue);
+ PublishNext(_lastInterpValue);
+ }
+ else if (playbackTime > iterDuration & playbackTime <= fullIterationTime & iterDelay > 0)
+ {
+ DoDelay();
+ }
}
}
}
-}
+}
\ No newline at end of file