背景
动画是应用程序与用户交互的灵魂。目前接触到的更多的关于动画的 官方资料 是通过 EventTrigger.RoutedEvent
事件属性与 BeginStoryboard
配合使用来达到动画的目的。
但是当我在开发过程中需要在指定属性变更之后,才开始动画。这个属性可以是一个 int
、bool
等任何类型的值。如果要实现值的绑定,在WPF中,需要使用 DataTrigger
。
以下是我解决该问题时的步骤。完整代码附在最后。
添加依赖属性
创建控件(控件添加一外名称属性 )后,添加一个依赖属性 AnimateStart
创建依赖属性的目的是为了在其他地方使用这个控件的时候,可以绑定到Model的属性上。
/// <summary>
/// 动画开始
/// </summary>
public bool AnimateStart
{
get { return (bool)GetValue(AnimateStartProperty); }
set { SetValue(AnimateStartProperty, value); }
}
// Using a DependencyProperty as the backing store for AnimateStart. This enables animation, styling, binding, etc...
public static readonly DependencyProperty AnimateStartProperty =
DependencyProperty.Register(nameof(AnimateStart), typeof(bool), typeof(SingleRecruit),
new PropertyMetadata(false));
在控件中,针对一个元素,在接下来的示例中,使用 Image
进行示范:
给 Image
添加 Style
同样的,与其他的 DataTrigger
使用方式相同,给 Image
添加 Style
,然后在 Style.Triggers
里面设置 DataTrigger
由于 DataTrigger
继承的是 TriggerBase
,详细文档看这里。
可以使用属性 EnterActions
、ExitActions
后设置动画。
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=UC, Path=AnimateStart}" Value="true">
<DataTrigger.EnterActions>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
针对 Image
控件的属性动画
如 Image.Opacity
属性,可以直接设置,不需要设置上述的 RenderTransform
节点。
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=UC, Path=AnimateStart}" Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
Duration="0:0:1" BeginTime="0:0:0"
From="1" To="0.2"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
针对 RenderTransform
节点的动画
在
Image
里添加RenderTransform
节点
添加 RenderTransform
节点的目的在于我们需要对其做位移、旋转、缩放、斜切动画时,需要针对该属性做设置,否则会报错。
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1"/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Image.RenderTransform>
注:此时不能针对
ScaleTransform
属性设置名称Name="ScaleProp"
,然后使用Storyboard.TargetName="ScaleProp"
方法绑定到Scale
属性中
解决办法如下,我们需要使用Storyboard.TargetProperty
来做一次转化
重点在于这一句Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=UC, Path=AnimateStart}" Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"
Duration="0:0:1" BeginTime="0:0:0"
From="1" To="-1"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
完整代码
<Image Source="<Your Image Source Path>"
RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1"/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Image.RenderTransform>
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=UC, Path=AnimateStart}" Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
Duration="0:0:1" BeginTime="0:0:0"
From="1" To="0.2"/>
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"
Duration="0:0:1" BeginTime="0:0:0"
From="1" To="-1"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>