Преглед изворни кода

Support gradients with not matched number of stops

Max Katz пре 4 година
родитељ
комит
b05ff7ccd8

+ 52 - 13
samples/RenderDemo/Pages/AnimationsPage.xaml

@@ -172,7 +172,7 @@
             </KeyFrame>
             <KeyFrame Cue="30%">
               <Setter Property="Background">
-                <LinearGradientBrush StartPoint="0%,0%" EndPoint="100%,100%">
+                <LinearGradientBrush StartPoint="0%,0%" EndPoint="0%,100%">
                   <GradientStop Offset="0" Color="Red"/>
                   <GradientStop Offset="1" Color="Blue"/>
                 </LinearGradientBrush>
@@ -183,7 +183,7 @@
             </KeyFrame>
             <KeyFrame Cue="100%">
               <Setter Property="Background">
-                <LinearGradientBrush StartPoint="100%,0%" EndPoint="0%,100%">
+                <LinearGradientBrush StartPoint="0%,0%" EndPoint="0%,100%">
                   <GradientStop Offset="0" Color="Green"/>
                   <GradientStop Offset="1" Color="Yellow"/>
                 </LinearGradientBrush>
@@ -200,20 +200,31 @@
                      PlaybackDirection="Alternate">
             <KeyFrame Cue="0%">
               <Setter Property="Background">
-                <LinearGradientBrush StartPoint="0%,0%" EndPoint="100%,100%">
+                <LinearGradientBrush StartPoint="0%,0%" EndPoint="0%,100%">
                   <GradientStop Offset="0" Color="Red"/>
                   <GradientStop Offset="1" Color="Blue"/>
                 </LinearGradientBrush>
               </Setter>
             </KeyFrame>
-            <KeyFrame Cue="100%">
+            <KeyFrame Cue="50%">
               <Setter Property="Background">
                 <LinearGradientBrush StartPoint="100%,0%" EndPoint="0%,100%">
-                  <GradientStop Offset="0" Color="Green"/>
+                  <GradientStop Offset="0" Color="Red"/>
+                  <GradientStop Offset="0.25" Color="Blue"/>
+                  <GradientStop Offset="0.5" Color="Blue"/>
+                  <GradientStop Offset="0.75" Color="Green"/>
                   <GradientStop Offset="1" Color="Yellow"/>
                 </LinearGradientBrush>
               </Setter>
             </KeyFrame>
+            <KeyFrame Cue="100%">
+              <Setter Property="Background">
+                <LinearGradientBrush StartPoint="0%,0%" EndPoint="0%,100%">
+                  <GradientStop Offset="0" Color="Red"/>
+                  <GradientStop Offset="1" Color="Blue"/>
+                </LinearGradientBrush>
+              </Setter>
+            </KeyFrame>
           </Animation>
         </Style.Animations>
       </Style>
@@ -226,16 +237,20 @@
             <KeyFrame Cue="0%">
               <Setter Property="Background">
                 <ConicGradientBrush Center="50%,50%" Angle="0">
-                  <GradientStop Offset="0" Color="Red"/>
+                  <GradientStop Offset="0" Color="Blue"/>
+                  <GradientStop Offset="0.5" Color="Red"/>
                   <GradientStop Offset="1" Color="Blue"/>
                 </ConicGradientBrush>
               </Setter>
             </KeyFrame>
             <KeyFrame Cue="100%">
               <Setter Property="Background">
-                <ConicGradientBrush Center="70%,70%" Angle="90">
+                <ConicGradientBrush Center="50%,70%" Angle="90">
                   <GradientStop Offset="0" Color="Green"/>
-                  <GradientStop Offset="1" Color="Yellow"/>
+                  <GradientStop Offset="0.25" Color="Yellow"/>
+                  <GradientStop Offset="0.5" Color="Red"/>
+                  <GradientStop Offset="0.75" Color="Blue"/>
+                  <GradientStop Offset="1" Color="Green"/>
                 </ConicGradientBrush>
               </Setter>
             </KeyFrame>
@@ -247,10 +262,34 @@
         <Style.Animations>
           <Animation Duration="0:0:3"
                      IterationCount="Infinite"
-                     PlaybackDirection="Alternate">
+                     PlaybackDirection="Normal">
             <KeyFrame Cue="0%">
               <Setter Property="Background">
-                <RadialGradientBrush Center="50%,50%" Radius="0.5">
+                <RadialGradientBrush Center="0%,100%" Radius="0.8">
+                  <GradientStop Offset="0" Color="Red"/>
+                  <GradientStop Offset="1" Color="Blue"/>
+                </RadialGradientBrush>
+              </Setter>
+            </KeyFrame>
+            <KeyFrame Cue="25%">
+              <Setter Property="Background">
+                <RadialGradientBrush Center="0%,0%" Radius="1">
+                  <GradientStop Offset="0" Color="Red"/>
+                  <GradientStop Offset="1" Color="Blue"/>
+                </RadialGradientBrush>
+              </Setter>
+            </KeyFrame>
+            <KeyFrame Cue="50%">
+              <Setter Property="Background">
+                <RadialGradientBrush Center="100%,0%" Radius="0.8">
+                  <GradientStop Offset="0" Color="Red"/>
+                  <GradientStop Offset="1" Color="Blue"/>
+                </RadialGradientBrush>
+              </Setter>
+            </KeyFrame>
+            <KeyFrame Cue="75%">
+              <Setter Property="Background">
+                <RadialGradientBrush Center="100%,100%" Radius="1">
                   <GradientStop Offset="0" Color="Red"/>
                   <GradientStop Offset="1" Color="Blue"/>
                 </RadialGradientBrush>
@@ -258,9 +297,9 @@
             </KeyFrame>
             <KeyFrame Cue="100%">
               <Setter Property="Background">
-                <RadialGradientBrush Center="30%,30%" Radius="0.2">
-                  <GradientStop Offset="0" Color="Green"/>
-                  <GradientStop Offset="1" Color="Yellow"/>
+                <RadialGradientBrush Center="0%,100%" Radius="0.8">
+                  <GradientStop Offset="0" Color="Red"/>
+                  <GradientStop Offset="1" Color="Blue"/>
                 </RadialGradientBrush>
               </Setter>
             </KeyFrame>

+ 25 - 13
src/Avalonia.Visuals/Animation/Animators/GradientBrushAnimator.cs

@@ -19,8 +19,7 @@ namespace Avalonia.Animation.Animators
 
         public override IGradientBrush? Interpolate(double progress, IGradientBrush? oldValue, IGradientBrush? newValue)
         {
-            if (oldValue is null || newValue is null
-                || oldValue.GradientStops.Count != newValue.GradientStops.Count)
+            if (oldValue is null || newValue is null)
             {
                 return progress >= 0.5 ? newValue : oldValue;
             }
@@ -64,13 +63,26 @@ namespace Avalonia.Animation.Animators
 
         private IReadOnlyList<ImmutableGradientStop> InterpolateStops(double progress, IReadOnlyList<IGradientStop> oldValue, IReadOnlyList<IGradientStop> newValue)
         {
-            var stops = new ImmutableGradientStop[oldValue.Count];
-            for (int index = 0; index < oldValue.Count; index++)
+            var resultCount = Math.Max(oldValue.Count, newValue.Count);
+            var stops = new ImmutableGradientStop[resultCount];
+
+            for (int index = 0, oldIndex = 0, newIndex = 0; index < resultCount; index++)
             {
                 stops[index] = new ImmutableGradientStop(
-                    s_doubleAnimator.Interpolate(progress, oldValue[index].Offset, newValue[index].Offset),
-                    ColorAnimator.InterpolateCore(progress, oldValue[index].Color, newValue[index].Color));
+                    s_doubleAnimator.Interpolate(progress, oldValue[oldIndex].Offset, newValue[newIndex].Offset),
+                    ColorAnimator.InterpolateCore(progress, oldValue[oldIndex].Color, newValue[newIndex].Color));
+
+                if (oldIndex < oldValue.Count - 1)
+                {
+                    oldIndex++;
+                }
+
+                if (newIndex < newValue.Count - 1)
+                {
+                    newIndex++;
+                }
             }
+            
             return stops;
         }
 
@@ -80,29 +92,29 @@ namespace Avalonia.Animation.Animators
             {
                 case IRadialGradientBrush oldRadial:
                     return new ImmutableRadialGradientBrush(
-                        CreateStopsFromSolidColorBrush(solidColorBrush, oldRadial), solidColorBrush.Opacity,
+                        CreateStopsFromSolidColorBrush(solidColorBrush, oldRadial.GradientStops), solidColorBrush.Opacity,
                         oldRadial.SpreadMethod, oldRadial.Center, oldRadial.GradientOrigin, oldRadial.Radius);
 
                 case IConicGradientBrush oldConic:
                     return new ImmutableConicGradientBrush(
-                        CreateStopsFromSolidColorBrush(solidColorBrush, oldConic), solidColorBrush.Opacity,
+                        CreateStopsFromSolidColorBrush(solidColorBrush, oldConic.GradientStops), solidColorBrush.Opacity,
                         oldConic.SpreadMethod, oldConic.Center, oldConic.Angle);
 
                 case ILinearGradientBrush oldLinear:
                     return new ImmutableLinearGradientBrush(
-                        CreateStopsFromSolidColorBrush(solidColorBrush, oldLinear), solidColorBrush.Opacity,
+                        CreateStopsFromSolidColorBrush(solidColorBrush, oldLinear.GradientStops), solidColorBrush.Opacity,
                         oldLinear.SpreadMethod, oldLinear.StartPoint, oldLinear.EndPoint);
 
                 default:
                     throw new NotSupportedException($"Gradient of type {gradientBrush?.GetType()} is not supported");
             }
 
-            static IReadOnlyList<ImmutableGradientStop> CreateStopsFromSolidColorBrush(ISolidColorBrush solidColorBrush, IGradientBrush baseGradient)
+            static IReadOnlyList<ImmutableGradientStop> CreateStopsFromSolidColorBrush(ISolidColorBrush solidColorBrush, IReadOnlyList<IGradientStop> baseStops)
             {
-                var stops = new ImmutableGradientStop[baseGradient.GradientStops.Count];
-                for (int index = 0; index < baseGradient.GradientStops.Count; index++)
+                var stops = new ImmutableGradientStop[baseStops.Count];
+                for (int index = 0; index < baseStops.Count; index++)
                 {
-                    stops[index] = new ImmutableGradientStop(baseGradient.GradientStops[index].Offset, solidColorBrush.Color);
+                    stops[index] = new ImmutableGradientStop(baseStops[index].Offset, solidColorBrush.Color);
                 }
                 return stops;
             }