Browse Source

Support gradients with not matched number of stops

pull/6183/head
Max Katz 5 years ago
parent
commit
b05ff7ccd8
  1. 65
      samples/RenderDemo/Pages/AnimationsPage.xaml
  2. 38
      src/Avalonia.Visuals/Animation/Animators/GradientBrushAnimator.cs

65
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>

38
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;
}

Loading…
Cancel
Save