瀏覽代碼

Merge branch 'master' into system-fonts

Jeffrey Ye 6 年之前
父節點
當前提交
a78f9b43bd

+ 13 - 8
src/Avalonia.Animation/AnimationInstance`1.cs

@@ -19,6 +19,7 @@ namespace Avalonia.Animation
         private ulong? _iterationCount;
         private ulong _currentIteration;
         private bool _gotFirstKFValue;
+        private bool _playbackReversed;
         private FillMode _fillMode;
         private PlaybackDirection _playbackDirection;
         private Animator<T> _animator;
@@ -160,9 +161,14 @@ namespace Avalonia.Animation
 
                 _currentIteration = (ulong)(opsTime / iterationTime);
 
-                // Stop animation when the current iteration is beyond the iteration count.
+                // Stop animation when the current iteration is beyond the iteration count
+                // and snap the last iteration value to exact values.
                 if ((_currentIteration + 1) > _iterationCount)
+                {
+                    var easedTime = _easeFunc.Ease(_playbackReversed ? 0.0 : 1.0);
+                    _lastInterpValue = _interpolator(easedTime, _neutralValue);
                     DoComplete();
+                }
 
                 if (playbackTime <= iterDuration)
                 {
@@ -170,27 +176,26 @@ namespace Avalonia.Animation
                     var normalizedTime = playbackTime / iterDuration;
 
                     // Check if normalized time needs to be reversed according to PlaybackDirection
-                    
-                    bool playbackReversed;
+
                     switch (_playbackDirection)
                     {
                         case PlaybackDirection.Normal:
-                            playbackReversed = false;
+                            _playbackReversed = false;
                             break;
                         case PlaybackDirection.Reverse:
-                            playbackReversed = true;
+                            _playbackReversed = true;
                             break;
                         case PlaybackDirection.Alternate:
-                            playbackReversed = (_currentIteration % 2 == 0) ? false : true;
+                            _playbackReversed = (_currentIteration % 2 == 0) ? false : true;
                             break;
                         case PlaybackDirection.AlternateReverse:
-                            playbackReversed = (_currentIteration % 2 == 0) ? true : false;
+                            _playbackReversed = (_currentIteration % 2 == 0) ? true : false;
                             break;
                         default:
                             throw new InvalidOperationException($"Animation direction value is unknown: {_playbackDirection}");
                     }
 
-                    if (playbackReversed)
+                    if (_playbackReversed)
                         normalizedTime = 1 - normalizedTime;
 
                     // Ease and interpolate

+ 54 - 0
tests/Avalonia.Animation.UnitTests/AnimationIterationTests.cs

@@ -8,6 +8,7 @@ using Avalonia.Styling;
 using Avalonia.UnitTests;
 using Avalonia.Data;
 using Xunit;
+using Avalonia.Animation.Easings;
 
 namespace Avalonia.Animation.UnitTests
 {
@@ -73,5 +74,58 @@ namespace Avalonia.Animation.UnitTests
             Assert.True(animationRun.Status == TaskStatus.RanToCompletion);
             Assert.Equal(border.Width, 100d);
         }
+
+        [Fact]
+        public void Check_FillModes_Start_and_End_Values_if_Retained()
+        {
+            var keyframe1 = new KeyFrame()
+            {
+                Setters =
+                {
+                    new Setter(Border.WidthProperty, 0d),
+                },
+                Cue = new Cue(0.0d)
+            };
+
+            var keyframe2 = new KeyFrame()
+            {
+                Setters =
+                {
+                    new Setter(Border.WidthProperty, 300d),
+                },
+                Cue = new Cue(1.0d)
+            };
+
+            var animation = new Animation()
+            {
+                Duration = TimeSpan.FromSeconds(0.05d),
+                Delay = TimeSpan.FromSeconds(0.05d),
+                Easing = new SineEaseInOut(),
+                FillMode = FillMode.Both,
+                Children =
+                {
+                    keyframe1,
+                    keyframe2
+                }
+            };
+
+            var border = new Border()
+            {
+                Height = 100d,
+                Width = 100d,
+            };
+
+            var clock = new TestClock();
+            var animationRun = animation.RunAsync(border, clock);
+
+            clock.Step(TimeSpan.FromSeconds(0d));
+            Assert.Equal(border.Width, 0d);
+
+            clock.Step(TimeSpan.FromSeconds(0.050d));
+            Assert.Equal(border.Width, 0d);
+
+            clock.Step(TimeSpan.FromSeconds(0.100d));
+            Assert.Equal(border.Width, 300d);
+        }
     }
 }