场景(Strouyboard)就是并行执行的一组动画(关键帧动画这是穿行执行的一组动画)。
设计WPF的场景时情况也差不多,先是吧一组独立的动画组织在一个Storyboard元素中、安排好它们的协作关系,然后指定哪个动画由哪个UI元素、哪个属性负责完成。Storyboard设计好后,你可以为它选择一个恰当的触发时机,比如按钮按下时或下载开始时。一旦触发条件被满足,动画场景就会开始执行,用户就会看到动画效果。
<Window x:Class="WPFLearn.DrawAndAnimation.StoryboardDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="StoryboardDemo" SizeToContent="WidthAndHeight">
<Grid Margin="6">
<!--布局控制-->
<Grid.RowDefinitions>
<RowDefinition Height="38"/>
<RowDefinition Height="38"/>
<RowDefinition Height="38"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="460"/>
<ColumnDefinition Width="60"/>
</Grid.ColumnDefinitions>
<!--跑道(红)-->
<Border BorderBrush="Gray" BorderThickness="1" Grid.Row="0">
<Ellipse x:Name="ballR" Height="36" Width="36" Fill="Red" HorizontalAlignment="Left">
<Ellipse.RenderTransform>
<TranslateTransform x:Name="ttR"/>
</Ellipse.RenderTransform>
</Ellipse>
</Border>
<!--跑道(绿)-->
<Border BorderBrush="Gray" BorderThickness="1,0,1,1" Grid.Row="1">
<Ellipse x:Name="ballG" Height="36" Width="36" Fill="LawnGreen" HorizontalAlignment="Left">
<Ellipse.RenderTransform>
<TranslateTransform x:Name="ttG"/>
</Ellipse.RenderTransform>
</Ellipse>
</Border>
<!--跑道(蓝)-->
<Border BorderBrush="Gray" BorderThickness="1,0,1,1" Grid.Row="2">
<Ellipse x:Name="ballB" Height="36" Width="36" Fill="Blue" HorizontalAlignment="Left">
<Ellipse.RenderTransform>
<TranslateTransform x:Name="ttB"/>
</Ellipse.RenderTransform>
</Ellipse>
</Border>
<!--按钮-->
<Button Content="Go!" Grid.Column="1" Grid.RowSpan="3" Click="Button_OnClick"/>
</Grid>
</Window>
private void Button_OnClick(object sender, RoutedEventArgs e)
{
Duration duration=new Duration(TimeSpan.FromMilliseconds(600));
// 红色小球匀速移动
DoubleAnimation daRx=new DoubleAnimation();
daRx.Duration = duration;
daRx.To = 400;
// 绿色小球变速运动
DoubleAnimationUsingKeyFrames dakGx=new DoubleAnimationUsingKeyFrames();
dakGx.Duration = duration;
SplineDoubleKeyFrame kfG = new SplineDoubleKeyFrame(400, KeyTime.FromPercent(1.0));
kfG.KeySpline=new KeySpline(1,0,0,1);
dakGx.KeyFrames.Add(kfG);
//蓝色小球变速运动
DoubleAnimationUsingKeyFrames dakBx=new DoubleAnimationUsingKeyFrames();
dakBx.Duration = duration;
SplineDoubleKeyFrame kfB = new SplineDoubleKeyFrame(400, KeyTime.FromPercent(1.0));
kfB.KeySpline = new KeySpline(0, 1, 1, 0);
dakBx.KeyFrames.Add(kfB);
// 创建场景
Storyboard storyboard=new Storyboard();
Storyboard.SetTargetName(daRx,"ttR");
Storyboard.SetTargetProperty(daRx,new PropertyPath(TranslateTransform.XProperty));
Storyboard.SetTargetName(dakGx, "ttG");
Storyboard.SetTargetProperty(dakGx, new PropertyPath(TranslateTransform.XProperty));
Storyboard.SetTargetName(dakBx, "ttB");
Storyboard.SetTargetProperty(dakBx, new PropertyPath(TranslateTransform.XProperty));
storyboard.Duration = duration;
storyboard.Children.Add(daRx);
storyboard.Children.Add(dakGx);
storyboard.Children.Add(dakBx);
storyboard.Begin(this);
storyboard.Completed += (a, b) => { MessageBox.Show(ttR.X.ToString()); };
}
毋庸置疑,使用C#代码实现Storyboard非常复杂,除了拿来做研究或遇到非得使用C#动态创建Storyboard的情况,不然我们都是用XAML代码创建Storyboard。Storyboard一般都放在UI元素的Trigger里,Trigger在触发时会执行<BeginStoryboard>标签中的Storyboard实例:
<Button Content="Go!" Grid.Column="1" Grid.RowSpan="3">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard Duration="0:0:0.6">
<!--红色小球动画-->
<DoubleAnimation Duration="0:0:0.6" To="400" Storyboard.TargetName="ttR" Storyboard.TargetProperty="X"/>
<!--绿色小球动画-->
<DoubleAnimationUsingKeyFrames Duration="0:0:0.6" Storyboard.TargetName="ttG" Storyboard.TargetProperty="X">
<SplineDoubleKeyFrame KeyTime="0:0:0.6" Value="400" KeySpline="1,0,0,1"/>
</DoubleAnimationUsingKeyFrames>
<!--红蓝小球动画-->
<DoubleAnimationUsingKeyFrames Duration="0:0:0.6" Storyboard.TargetName="ttB" Storyboard.TargetProperty="X">
<SplineDoubleKeyFrame KeyTime="0:0:0.6" Value="400" KeySpline="0,1,1,0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
除了为Button添加了Trigger并去掉对Click事件的订阅之处,XAML代码其他的部分不做任何改动。可以看到,使用XAML代码编写Storyboard动画比用C#代码简洁得多---Blend生成的Storyboard代码与之非常类似。