C# 在按钮上的两个WPF渐变之间创建过渡?
我有这个按钮: 由以下XAML代码组成:C# 在按钮上的两个WPF渐变之间创建过渡?,c#,wpf,xaml,C#,Wpf,Xaml,我有这个按钮: 由以下XAML代码组成: <Style TargetType="{x:Type Button}" x:Key="GreenButtonStyle" BasedOn="{StaticResource {x:Type Button}}"> <Setter Property="Foreground" Value="#fff" /> <Setter Property="Template"> <Setter.Val
<Style TargetType="{x:Type Button}" x:Key="GreenButtonStyle" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Foreground" Value="#fff" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="border" BorderThickness="1" BorderBrush="#446c06" CornerRadius="3" Background="{TemplateBinding Background}">
<Border BorderBrush="#55ffffff" BorderThickness="1" CornerRadius="3" Padding="6,4">
<Grid>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Name="contentShadow" Style="{StaticResource ShadowStyle}">
<ContentPresenter.RenderTransform>
<TranslateTransform X="1.0" Y="1.0" />
</ContentPresenter.RenderTransform>
</ContentPresenter>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Name="content" />
</Grid>
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#aae64b" Offset="0"/>
<GradientStop Color="#7eb922" Offset="0.16"/>
<GradientStop Color="#6aa016" Offset="0.57"/>
<GradientStop Color="#649714" Offset="0.86"/>
<GradientStop Color="#7eb922" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#bbf75c" Offset="0"/>
<GradientStop Color="#8fba33" Offset="0.16"/>
<GradientStop Color="#7bb127" Offset="0.57"/>
<GradientStop Color="#75a825" Offset="0.86"/>
<GradientStop Color="#8fca33" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" >
<Setter.Value>
<LinearGradientBrush StartPoint="0,1" EndPoint="0,0" >
<GradientStop Color="#aae64b" Offset="0"/>
<GradientStop Color="#7eb922" Offset="0.16"/>
<GradientStop Color="#6aa016" Offset="0.57"/>
<GradientStop Color="#649714" Offset="0.86"/>
<GradientStop Color="#7eb922" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter TargetName="content" Property="RenderTransform" >
<Setter.Value>
<TranslateTransform Y="1.0" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
一切正常,除了我想在鼠标状态之间进行转换/动画(按下+正常+悬停)
我在网上找到了一些指南,它们为每个渐变停止属性设置动画,但我不想这样做。我只想在渐变之间有一个直接的过渡
有没有一种简单的方法可以在不设置每个渐变停止属性动画的情况下执行此操作?您可以覆盖两个矩形,每个矩形都用渐变填充,并设置顶部矩形不透明度的动画 这可能看起来不错,也可能不好,这取决于您对过渡的期望
如果你有冒险的感觉:没有线性辐射,但你可以做到…正如Erno所指出的,没有
线性辐射,但它可以以与彩色动画
相同的方式创建。如果我们看一下ColorAnimation
的实现,我们会发现它使用了如下辅助函数
AddColor(颜色值1,颜色值2)
SubtractColor(颜色值1,颜色值2)
ScaleColor(颜色值,双因子)
interpoleColor(颜色从、颜色到、双进度)
要创建LinearGradientAnimation
我们需要相同的函数,但对于LinearGradientBrush
而不是Color
。我创造了这样一个动画,它似乎工作的预期。一个要求是To
和From
值具有相同的GradientStops
像这样是有用的
<Storyboard>
<ani:LinearGradientAnimation Storyboard.TargetProperty="Background"
Duration="0:0:0.2"
From="{StaticResource NormalBrush}"
To="{StaticResource MouseOverBrush}"/>
</Storyboard>
你还需要
internal enum AnimationType : byte
{
Automatic,
From,
To,
By,
FromTo,
FromBy
}
很好的例子。谢谢
public class LinearGradientAnimation : AnimationTimeline
{
#region Dependency Properties
public static readonly DependencyProperty FromProperty =
DependencyProperty.Register("From",
typeof(LinearGradientBrush),
typeof(LinearGradientAnimation),
new PropertyMetadata(null, AnimationFunction_Changed));
public static readonly DependencyProperty ToProperty =
DependencyProperty.Register("To",
typeof(LinearGradientBrush),
typeof(LinearGradientAnimation),
new PropertyMetadata(null, AnimationFunction_Changed));
public static readonly DependencyProperty ByProperty =
DependencyProperty.Register("By",
typeof(LinearGradientBrush),
typeof(LinearGradientAnimation),
new PropertyMetadata(null, AnimationFunction_Changed));
public static readonly DependencyProperty EasingFunctionProperty =
DependencyProperty.Register("EasingFunction",
typeof(IEasingFunction),
typeof(LinearGradientAnimation));
private static void AnimationFunction_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
LinearGradientAnimation linearGradientAnimation = (LinearGradientAnimation)d;
linearGradientAnimation._isAnimationFunctionValid = false;
}
#endregion // Dependency Properties
#region Private Fields
private LinearGradientBrush[] _keyValues;
private AnimationType _animationType;
private bool _isAnimationFunctionValid;
#endregion // Private Fields
#region Constructor
public LinearGradientAnimation()
{
}
public LinearGradientAnimation(LinearGradientBrush toValue, Duration duration)
: this()
{
this.To = toValue;
base.Duration = duration;
}
public LinearGradientAnimation(LinearGradientBrush toValue, Duration duration, FillBehavior fillBehavior)
: this()
{
this.To = toValue;
base.Duration = duration;
base.FillBehavior = fillBehavior;
}
public LinearGradientAnimation(LinearGradientBrush fromValue, LinearGradientBrush toValue, Duration duration)
: this()
{
this.From = fromValue;
this.To = toValue;
base.Duration = duration;
}
public LinearGradientAnimation(LinearGradientBrush fromValue, LinearGradientBrush toValue, Duration duration, FillBehavior fillBehavior)
: this()
{
this.From = fromValue;
this.To = toValue;
base.Duration = duration;
base.FillBehavior = fillBehavior;
}
#endregion // Constructor
#region Properties
public LinearGradientBrush From
{
get { return (LinearGradientBrush)base.GetValue(LinearGradientAnimation.FromProperty); }
set { base.SetValue(LinearGradientAnimation.FromProperty, value); }
}
public LinearGradientBrush To
{
get { return (LinearGradientBrush)base.GetValue(LinearGradientAnimation.ToProperty); }
set { base.SetValue(LinearGradientAnimation.ToProperty, value); }
}
public LinearGradientBrush By
{
get { return (LinearGradientBrush)base.GetValue(LinearGradientAnimation.ByProperty); }
set { base.SetValue(LinearGradientAnimation.ByProperty, value); }
}
public IEasingFunction EasingFunction
{
get { return (IEasingFunction)base.GetValue(LinearGradientAnimation.EasingFunctionProperty); }
set { base.SetValue(LinearGradientAnimation.EasingFunctionProperty, value); }
}
public bool IsAdditive
{
get { return (bool)base.GetValue(AnimationTimeline.IsAdditiveProperty); }
set { base.SetValue(AnimationTimeline.IsAdditiveProperty, value); }
}
public bool IsCumulative
{
get { return (bool)base.GetValue(AnimationTimeline.IsCumulativeProperty); }
set { base.SetValue(AnimationTimeline.IsCumulativeProperty, value); }
}
#endregion // Properties
#region Private Methods
protected LinearGradientBrush GetCurrentValueCore(LinearGradientBrush defaultOriginValue, LinearGradientBrush defaultDestinationValue, AnimationClock animationClock)
{
if (!this._isAnimationFunctionValid)
{
this.ValidateAnimationFunction();
}
double num = animationClock.CurrentProgress.Value;
IEasingFunction easingFunction = this.EasingFunction;
if (easingFunction != null)
{
num = easingFunction.Ease(num);
}
LinearGradientBrush brush = null;
LinearGradientBrush brush2 = null;
LinearGradientBrush value = null;
LinearGradientBrush value2 = null;
switch (this._animationType)
{
case AnimationType.Automatic:
brush = defaultOriginValue;
brush2 = defaultDestinationValue;
value = GetDefaultLinearGradientBrush(brush);
value2 = GetDefaultLinearGradientBrush(brush);
break;
case AnimationType.From:
brush = this._keyValues[0];
brush2 = defaultDestinationValue;
value = GetDefaultLinearGradientBrush(brush);
value2 = GetDefaultLinearGradientBrush(brush);
break;
case AnimationType.To:
brush = defaultOriginValue;
brush2 = this._keyValues[0];
value = GetDefaultLinearGradientBrush(brush2);
value2 = GetDefaultLinearGradientBrush(brush2);
break;
case AnimationType.By:
brush2 = this._keyValues[0];
value2 = defaultOriginValue;
value = GetDefaultLinearGradientBrush(brush2);
value2 = GetDefaultLinearGradientBrush(brush2);
break;
case AnimationType.FromTo:
brush = this._keyValues[0];
brush2 = this._keyValues[1];
value = GetDefaultLinearGradientBrush(brush);
value2 = GetDefaultLinearGradientBrush(brush);
if (this.IsAdditive)
{
value2 = defaultOriginValue;
}
break;
case AnimationType.FromBy:
brush = this._keyValues[0];
brush2 = AddLinearGradientBrush(this._keyValues[0], this._keyValues[1]);
value = GetDefaultLinearGradientBrush(brush);
value2 = GetDefaultLinearGradientBrush(brush);
if (this.IsAdditive)
{
value2 = defaultOriginValue;
}
break;
}
if (this.IsCumulative)
{
double num2 = (double)(animationClock.CurrentIteration - 1).Value;
if (num2 > 0.0)
{
LinearGradientBrush value3 = SubtractLinearGradientBrush(brush2, brush);
value = ScaleLinearGradientBrush(value3, num2);
}
}
LinearGradientBrush returnBrush = AddLinearGradientBrush(value2, AddLinearGradientBrush(value, InterpolateGradientBrush(brush, brush2, num)));
return returnBrush;
}
private LinearGradientBrush GetDefaultLinearGradientBrush(LinearGradientBrush brush)
{
LinearGradientBrush returnBrush = new LinearGradientBrush();
returnBrush.StartPoint = default(Point);
returnBrush.EndPoint = default(Point);
for (int i = 0; i < brush.GradientStops.Count; i++)
{
returnBrush.GradientStops.Add(new GradientStop(default(Color), default(double)));
}
return returnBrush;
}
private void ValidateAnimationFunction()
{
this._animationType = AnimationType.Automatic;
this._keyValues = null;
if (this.From != null)
{
if (this.To != null)
{
this._animationType = AnimationType.FromTo;
this._keyValues = new LinearGradientBrush[2];
this._keyValues[0] = this.From;
this._keyValues[1] = this.To;
}
else
{
if (this.By != null)
{
this._animationType = AnimationType.FromBy;
this._keyValues = new LinearGradientBrush[2];
this._keyValues[0] = this.From;
this._keyValues[1] = this.By;
}
else
{
this._animationType = AnimationType.From;
this._keyValues = new LinearGradientBrush[1];
this._keyValues[0] = this.From;
}
}
}
else
{
if (this.To != null)
{
this._animationType = AnimationType.To;
this._keyValues = new LinearGradientBrush[1];
this._keyValues[0] = this.To;
}
else
{
if (this.By != null)
{
this._animationType = AnimationType.By;
this._keyValues = new LinearGradientBrush[1];
this._keyValues[0] = this.By;
}
}
}
this._isAnimationFunctionValid = true;
}
#endregion // Private Methods
#region AnimationTimeline / Freezable Members
public override Type TargetPropertyType
{
get { return typeof(LinearGradientBrush); }
}
public override object GetCurrentValue(object defaultOriginValue, object defaultDestinationValue, AnimationClock animationClock)
{
if (defaultOriginValue == null)
{
throw new ArgumentNullException("defaultOriginValue");
}
if (defaultDestinationValue == null)
{
throw new ArgumentNullException("defaultDestinationValue");
}
return this.GetCurrentValue((LinearGradientBrush)defaultOriginValue, (LinearGradientBrush)defaultDestinationValue, animationClock);
}
public LinearGradientBrush GetCurrentValue(LinearGradientBrush defaultOriginValue, LinearGradientBrush defaultDestinationValue, AnimationClock animationClock)
{
base.ReadPreamble();
if (animationClock == null)
{
throw new ArgumentNullException("animationClock");
}
if (animationClock.CurrentState == ClockState.Stopped)
{
return defaultDestinationValue;
}
return this.GetCurrentValueCore(defaultOriginValue, defaultDestinationValue, animationClock);
}
public new LinearGradientAnimation Clone()
{
return (LinearGradientAnimation)base.Clone();
}
protected override Freezable CreateInstanceCore()
{
return new LinearGradientAnimation();
}
#endregion // AnimationTimeline / Freezable Members
#region Helper Methods
internal static LinearGradientBrush AddLinearGradientBrush(LinearGradientBrush brush1, LinearGradientBrush brush2)
{
LinearGradientBrush gradientBrush = new LinearGradientBrush();
gradientBrush.StartPoint = AddPoint(brush1.StartPoint, brush2.StartPoint);
gradientBrush.EndPoint = AddPoint(brush1.EndPoint, brush2.EndPoint);
for (int i = 0; i < brush1.GradientStops.Count; i++)
{
GradientStop gradientStop1 = brush1.GradientStops[i];
GradientStop gradientStop2 = brush2.GradientStops[i];
Color color = AddColor(gradientStop1.Color, gradientStop2.Color);
double offset = AddDouble(gradientStop1.Offset, gradientStop2.Offset);
gradientBrush.GradientStops.Add(new GradientStop(color, offset));
}
return gradientBrush;
}
internal static LinearGradientBrush SubtractLinearGradientBrush(LinearGradientBrush brush1, LinearGradientBrush brush2)
{
LinearGradientBrush gradientBrush = new LinearGradientBrush();
gradientBrush.StartPoint = SubtractPoint(brush1.StartPoint, brush2.StartPoint);
gradientBrush.EndPoint = SubtractPoint(brush1.EndPoint, brush2.EndPoint);
for (int i = 0; i < brush1.GradientStops.Count; i++)
{
GradientStop gradientStop1 = brush1.GradientStops[i];
GradientStop gradientStop2 = brush2.GradientStops[i];
Color color = SubtractColor(gradientStop1.Color, gradientStop2.Color);
double offset = SubtractDouble(gradientStop1.Offset, gradientStop2.Offset);
gradientBrush.GradientStops.Add(new GradientStop(color, offset));
}
return gradientBrush;
}
internal static LinearGradientBrush ScaleLinearGradientBrush(LinearGradientBrush value, double factor)
{
LinearGradientBrush gradientBrush = new LinearGradientBrush();
gradientBrush.StartPoint = ScalePoint(value.StartPoint, factor);
gradientBrush.EndPoint = ScalePoint(value.EndPoint, factor);
for (int i = 0; i < value.GradientStops.Count; i++)
{
Color color = ScaleColor(value.GradientStops[i].Color, factor);
double offset = ScaleDouble(value.GradientStops[i].Offset, factor);
gradientBrush.GradientStops.Add(new GradientStop(color, offset));
}
return gradientBrush;
}
internal static LinearGradientBrush InterpolateGradientBrush(LinearGradientBrush from, LinearGradientBrush to, double progress)
{
LinearGradientBrush gradientBrush = new LinearGradientBrush();
gradientBrush.StartPoint = InterpolatePoint(from.StartPoint, to.StartPoint, progress);
gradientBrush.EndPoint = InterpolatePoint(from.EndPoint, to.EndPoint, progress);
for (int i = 0; i < from.GradientStops.Count; i++)
{
Color color = InterpolateColor(from.GradientStops[i].Color, to.GradientStops[i].Color, progress);
double offset = InterpolateDouble(from.GradientStops[i].Offset, to.GradientStops[i].Offset, progress);
gradientBrush.GradientStops.Add(new GradientStop(color, offset));
}
return gradientBrush;
}
internal static Color AddColor(Color value1, Color value2)
{
return value1 + value2;
}
internal static Color SubtractColor(Color value1, Color value2)
{
return value1 - value2;
}
internal static Color ScaleColor(Color value, double factor)
{
return value * (float)factor;
}
internal static Color InterpolateColor(Color from, Color to, double progress)
{
return from + (to - from) * (float)progress;
}
internal static double AddDouble(double value1, double value2)
{
return value1 + value2;
}
internal static double SubtractDouble(double value1, double value2)
{
return value1 - value2;
}
internal static double ScaleDouble(double value, double factor)
{
return value * factor;
}
internal static double InterpolateDouble(double from, double to, double progress)
{
return from + (to - from) * progress;
}
internal static Point AddPoint(Point value1, Point value2)
{
return new Point(value1.X + value2.X, value1.Y + value2.Y);
}
internal static Point SubtractPoint(Point value1, Point value2)
{
return new Point(value1.X - value2.X, value1.Y - value2.Y);
}
internal static Point ScalePoint(Point value, double factor)
{
return new Point(value.X * factor, value.Y * factor);
}
internal static Point InterpolatePoint(Point from, Point to, double progress)
{
return from + (to - from) * progress;
}
#endregion // Helper Methods
}
internal enum AnimationType : byte
{
Automatic,
From,
To,
By,
FromTo,
FromBy
}