关键帧动画和插值动画类似,同样可以根据目标属性值的变化产生相应的动画效果,不同的是,插值动画是在两个属性值之间进行渐变,而关键帧动画打破了仅通过两个属性值控制动画的局限性,它可以在任意多个属性值之间进行变化,这种变化方式可以是线性渐变也可以是瞬间突变。开发人员可以根据应用本身的需求,通过不同的关键帧设置动画元素的多个属性值,制作出更加复杂和绚丽的动画效果。
1.DoubleAnimationUsingKeyFrames关键帧动画
DoubleAnimationUsingKeyFrames关键帧动画一般包含LinearDoubleKeyFrame、SplineDoubleKeyFrame和DiscreteDoubleKeyFrame关键帧,这3个关键帧可以看做是动画效果的一个组合,随着动画在总时间线上进行,每个关键帧都会指定一个特定的值以产生不同的动画效果。并且通过控制Double类型的属性值可以使动画以连续或间断的方式进行播放。为了帮助读者理解DoubleAnimationUsingKeyFrames关键帧动画,下面首先介绍LinearDoubleKeyFrame、SplineDoubleKeyFrame和DiscreteDoubleKeyFrame这3个关键帧的作用。
q LinearDoubleKeyFrame,使元素的属性值在一段时间内进行固定速度的渐变,即属性值随时间的改变而改变,并且这种改变会实时的反映出来。
q SplineDoubleKeyFrame,用于对元素的属性值进行精确的渐变,通过设置KeySpline属性值可以控制渐变,产生一个可变的过程。
q DiscreteDoubleKeyFrame,使元素的属性值从一个值突变到另一个值,中间不会有任何渐变或变化过程。
了解了上述的关键帧之后,下面以DoubleAnimationUsingKeyFrames关键帧动画为例,实现一个改变椭圆宽度的动画效果。
在一个打开的Windows应用商店项目中新建一个空白页,并命名为DoubleAnimationUsingKeyFramesPage。打开此页面的DoubleAnimationUsingKeyFramesPage.xaml文件,使用如下代码替换原有的Grid元素。
<Grid Background="White">
<Ellipse x:Name="AnimationEllipse" PointerPressed="AnimationEllipse_Click" Fill="Blue" Width="100" Height="100"/>
<StackPanel>
<StackPanel.Resources>
<Storyboard x:Name="storyboard">
<DoubleAnimationUsingKeyFrames
EnableDependentAnimation="True"
Storyboard.TargetName="AnimationEllipse"
Storyboard.TargetProperty="Width">
<!--这个关键帧将动画重置为起始值为100像素的线性平滑动画-->
<LinearDoubleKeyFrame Value="100" KeyTime="0:0:0"/>
<!--这个关键帧动画开始时比较慢,之后加速将椭圆宽度增大到180像素-->
<SplineDoubleKeyFrame KeySpline="0,0 1,0" Value="180" KeyTime="0:0:0.8"/>
<!--在这里的弹跳动画中,椭圆最初快速减小宽度,然后慢下来直到停止-->
<SplineDoubleKeyFrame KeySpline="0.10, 0.21 0.00, 1.0" Value="130" KeyTime="0:0:1.5"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard >
</StackPanel.Resources>
</StackPanel>
</Grid>
在上面的代码中,首先添加一个名为“AnimationEllipse”的Ellipse元素,设置Fill 属性的值为蓝色(Blue),Width 和Height 属性的值分别为100像素,并为Ellipse元素添加一个用于启动动画的PointerPressed事件及事件处理方法。
接着添加一个StackPanel元素,并在StackPanel元素的资源字典StackPanel.Resources添加一个作为动画资源的Storyboard元素,并将其命名为storyboard,以便在后台文件中使用Storyboard对象启动动画。然后在Storyboard 元素中添加一个DoubleAnimationUsingKeyFrames动画,并通过TargetProperty属性设置动画控制的目标属性为Width,由于Width属性值的变化会影响到界面布局,因此要将EnableDependentAnimation属性值设置为True,以确保动画能够播放。设置Storyboard元素的TargetName属性值为AnimationRectangle,将动画效果定位到Ellipse元素上。
在关键帧动画DoubleAnimationUsingKeyFrames中添加一个LinearDoubleKeyFrame 关键帧,并通过其Value属性指定关键帧的目标值为100,使用KeyTime属性指定到达关键帧Value值的时间为0秒,这表示动画开始时将Ellipse元素的宽度设置为100像素。紧接着添加一个SplineDoubleKeyFrame关键帧,并设置其Value属性的值为180、KeyTime属性的值为0.8,表示在0.8秒时Ellipse元素的宽度将变为180像素。KeySpline属性可以通过指定贝塞尔曲线的第一个控制点和第二个控制点来记录动画的加速过程,将KeySpline属性赋值为“0,0 1,0”表示动画的速度逐渐变慢。最后再添加一个SplineDoubleKeyFrame关键帧并设置其相关属性,以便与前两个关键帧配合实现椭圆宽度先变大后变小的动画效果。
接下来打开DoubleAnimationUsingKeyFramesPage.xaml.cs文件,为PointerPressed事件添加事件处理方法AnimationEllipse_Click,通过调用storyboard对象的Begin方法启动关键帧动画的播放,实现代码如下所示:
private void AnimationEllipse_Click (object sender, PointerRoutedEventArgs e)
{
storyboard.Begin();
}
运行此页面,然后单击屏幕中的椭圆,可以看到此椭圆的宽度大小在整个动画周期内会产生加速和减速交替变化的动画效果。如图10-7所示。
图10-7 DoubleAnimationUsingKeyFrames动画效果
2.ColorAnimationUsingKeyFrames关键帧动画
ColorAnimationUsingKeyFrames关键帧动画与DoubleAnimationUsingKeyFrames关键帧动画的实现很相似,不同的是ColorAnimationUsingKeyFrames关键帧动画通过控制Color类型的属性值来实现动画效果,它一般包含LinearColorKeyFrame、DiscreteColorKeyFrame和SplineColorKeyFrame关键帧,这3个关键帧同样可以看做是动画效果的一个组合,每个关键帧都会指定一个值,随着动画在总时间线上进行,每个关键帧都会产生不同的动画效果。下面通过一个示例讲解如何添加ColorAnimationUsingKeyFrames关键帧动画,使Canvas元素的背景色在动画周期内产生渐变和突变的动画效果。
在一个打开的Windows 应用商店项目中新建一个空白页,并命名为ColorAnimationUsingKeyFramesPage。双击打开此页面的ColorAnimationUsingKeyFramesPage.xaml文件,在Grid元素中添加如下代码。
<Canvas Width="200" Height="200" Background="White" x:Name="ColorCanvas">
<Canvas.Triggers>
<EventTrigger RoutedEvent="Canvas.Loaded">
<BeginStoryboard>
<Storyboard>
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ColorCanvas" RepeatBehavior="Forever" EnableDependentAnimation="True" Storyboard.TargetProperty="(Canvas.Background).(SolidColorBrush.Color)">
<LinearColorKeyFrame Value="Red" KeyTime="00:00:02"/>
<DiscreteColorKeyFrame Value="Yellow" KeyTime="00:00:2.5"/>
<SplineColorKeyFrame Value="Green" KeyTime="00:00:4.5" KeySpline="0.6,0.0 0.9,0.00"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Canvas.Triggers>
</Canvas>
在上面的代码中,添加了一个名为ColorCanvas的Canvas元素,设置其Background属性值为白色(White),Width和Heiht属性值分别为200像素。接着在Canvas.Trigger元素中定义一个用于触发事件的EventTrigger元素,指定此元素的RoutedEvent属性的值为“Canvas.Loaded”,以便加载完Canvas元素后启动动画。接下来在EventTrigger元素中添加一个BeginStoryboard元素,并在其中添加一个用于添加动画的Storyboard元素,在Storyboard元素中添加了一个ColorAnimationUsingKeyFrames动画对象,并在其中设置Storyboard元素的TargetProperty属性值为(Canvas.Background).(SolidColorBrush.Color),以指定Canvas元素SolidColorBrush类型的背景色为动画目标属性。最后在ColorAnimationUsingKeyFrames动画中添加LinearColorKeyFrame、DiscreteColorKeyFrame和SplineColorKeyFrame 3个关键帧,在不同的关键帧中Canvas元素的背景色会发生变化。
运行此页面,可以看到Canvas元素的背景色会以渐变和突变的形式不断的变化,为了更好的理解每一时刻的详细变化情况,下面列举了在动画周期内这3个关键帧的动画效果。
q LinearColorKeyFrame线性关键帧,在两个值之间创建平滑的线性过渡,前两秒内Canvas元素的背景色逐渐从白色变为红色。
q DiscreteColorKeyFrame离散关键帧,在接下来的半秒内Canvas元素的背景色将快速的从红色变为黄色,此关键帧会在各个值之间突然的变化。
q SplineColorKeyFrame关键帧,在最后两秒内Canvas元素的背景色会再次更改颜色,这一次是从黄色变回绿色。 此关键帧将会根据KeySpline属性值在各个值之间创建可变过渡。在本示例中,颜色变化开始时比较缓慢,然后呈指数方式加速直到此关键帧结束。
3.ObjectAnimationUsingKeyFrames关键帧动画
ObjectAnimationUsingKeyFrames关键帧动画通过控制Object类型的属性值来实现相应的动画效果,可以包含一个或多个DiscreteObjectKeyFrame元素并以离散的属性值对该属性进行赋值,从而使动画呈现一种非连续的变化效果。下面以ObjectAnimationUsingKeyFrames关键帧动画为例,呈现一种使矩形填充色非连续变化的动画效果。
在一个打开的Windows应用商店项目中新建一个空白页,并命名为ObjectAnimationUsingKeyFramesPage。双击打开此页面的ObjectAnimationUsingKeyFrames.xaml文件,在Grid元素中添加如下代码。
<StackPanel.Resources>
<Storyboard x:Name="storyboard">
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="AnimatedRectangle" Storyboard.TargetProperty="Fill" Duration="0:0:3" RepeatBehavior="Forever">
<ObjectAnimationUsingKeyFrames.KeyFrames>
<DiscreteObjectKeyFrame KeyTime="0:0:1">
<DiscreteObjectKeyFrame.Value>
<LinearGradientBrush>
<!--为矩形Fill属性设置3种线性渐变Color属性值-->
<LinearGradientBrush.GradientStops>
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Orange" Offset="0.5" />
<GradientStop Color="Red" Offset="1.0" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:2">
<DiscreteObjectKeyFrame.Value>
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStop Color="White" Offset="0.0" />
<GradientStop Color="MediumBlue" Offset="0.5" />
<GradientStop Color="Black" Offset="1.0" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames.KeyFrames>
</ObjectAnimationUsingKeyFrames>
</Storyboard >
</StackPanel.Resources>
<!--加载关键帧动画的矩形-->
</StackPanel>
<Rectangle x:Name="AnimatedRectangle" Loaded="Rectangle_Loaded" Width="300" Height="300"/>
以上代码首先添加了一个StackPanel元素,并在StackPanel元素的资源字典StackPanel.Resources中添加了一个作为动画资源的Storyboard元素,并命名为storyboard,以便在后台文件中通过此名称启动动画。接着在Storyboard 元素中添加一个关键帧动画ObjectAnimationUsingKeyFrames,并使用TargetProperty属性指定动画控制的属性为Fill,同时通过Duration属性设定动画周期为3秒,并设置RepeatBehavior属性的值为Forever,这样动画将会一直播放。
接着为关键帧动画ObjectAnimationUsingKeyFrames添加两个DiscreteObjectKeyFrame关键帧,通过KeyTime属性设置第一个关键帧动画开始的时间为第1秒,第2个关键帧动画开始的时间为第2秒,同时为每个关键帧都指定一个含有3种颜色的渐变色,以便在不同的时间点突变为不同的颜色。然后添加一个名为“AnimatedRectangle”的Rectangle元素,并为其添加一个名为" Rectangle_Loaded "的Loaded 事件,最后设置Storyboard元素的TargetName属性值为AnimatedRectangle,将关键帧动画效果定位到Rectangle元素上。
接下来打开ObjectAnimationUsingKeyFrames.xaml.cs文件,为Rectangle元素的Loaded事件添加事件处理方法Rectangle_Loaded,代码如下所示:
以上Rectangle_Loaded事件处理方法通过调用storyboard对象的Begin方法能够实现启动关键帧动画的操作。运行此页面,读者会发现矩形的颜色在动画开始的第1秒和第2秒时会突变为两种不同的线性渐变色。
至此已经介绍了如何在演示图板中添加主题动画、插值动画以及关键帧动画。然而在实际开发中,为了提高开发效率,通常会选择使用Blend for Visual Studio 2012开发工具来添加演示图板动画,简单快速的动画设计能力是Blend for Visual Studio 2012开发工具的亮点,开发人员可以在设计整个动画的过程中实时地观察动画运行效果,而无需运行整个项目。有关此开发工具的相关知识读者可以查看相关书籍进行学习,这里将不做过多介绍。