WPF快速指导15:动画
在WPF或者SilverLight中,所谓动画,就是让一个对象的属性,随着时间而发生变化。动画由时间线(timeline)控制。时间线在C#中的原型为:
public abstract class Timeline : Animatable
{
//省略
}
它是一个抽象类。在WPF中,定义了各类时间线,最常用的有DoubleAnimation,它便继承自Timeline。
1:Storyboard及一个简单示例
容纳时间线的是故事板(Storyboard)。下面是一个最简单的例子:
前台:
<Canvas x:Name="Carrier" Width="800" Height="600" Background="Silver" MouseLeftButtonDown="Carrier_MouseLeftButtonDown" >
<Image x:Name="image1" Source="/WpfApplication1;component/run.jpg">
</Image>
<Button x:Name="buttonTest" Click="buttonTest_Click" Canvas.Top="250" Content="测试">
</Button>
</Canvas>
后台:
private void buttonTest_Click(object sender, RoutedEventArgs e)
{
TranslateTransform animatedTranslateTransform = new TranslateTransform();
image1.RenderTransform = animatedTranslateTransform;
DoubleAnimation doubleAnimation = new DoubleAnimation(0, 360, new Duration(TimeSpan.FromMilliseconds(1000)));
this.RegisterName("AnimatedTranslateTransform", animatedTranslateTransform);
Storyboard.SetTargetName(doubleAnimation, "AnimatedTranslateTransform");
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath(TranslateTransform.XProperty));
Storyboard translationStoryboard = new Storyboard();
translationStoryboard.Children.Add(doubleAnimation);
translationStoryboard.Begin(this);
}
在这个示例中,Storyboard中,我们使用了DoubleAnimation对象,它表示:随着时间改变一个数值。Storyboard通过SetTargetName方法将DoubleAnimation对象和animatedTranslateTransform联系起来。而animatedTranslateTransform又被指向image1.RenderTransform(关于RenderTransform属性,不明白的可以查看上篇《WPF快速指导14:变换》)。这就相当于说,动画被关联到了image1对象上。
这里面要重点讲一下SetTargetProperty方法。该方法第一个参数指定动画对象,第二个方法指的是,在SetTarget方法中被关联的那个的对象的一个属性。在本文的实例中,这个属性是TranslateTransform.XProperty。串联起来,本示例的需求就是:“在1000毫秒的时间里,让image1的TranslateTransform.XProperty属性由0变为360”。如果我们换一个属性,如TranslateTransform.XProperty,则表达的意思是:“在1000毫秒的时间里,让image1离最高处由0变为360”。
本示例运行效果:
2:关键帧
在上面的这个例子中,我们使用的线性插值。为了调整这个行为,可以用一组关键帧(key frame)来过渡。这也就是说,为了更改动画从起始属性到结束属性的线性行为,可插入一个或者多个关键帧。查看下面的示例:
TranslateTransform animatedTranslateTransform = new TranslateTransform();
image1.RenderTransform = animatedTranslateTransform;
this.RegisterName("AnimatedTranslateTransform", animatedTranslateTransform);
DoubleAnimationUsingKeyFrames translationAnimation = new DoubleAnimationUsingKeyFrames();
translationAnimation.Duration = TimeSpan.FromSeconds(6);
translationAnimation.KeyFrames.Add(new LinearDoubleKeyFrame(500, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(3))));
translationAnimation.KeyFrames.Add(new DiscreteDoubleKeyFrame(400, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(4))));
translationAnimation.KeyFrames.Add(new SplineDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(6)), new KeySpline(0.6, 0.0, 0.9,
0.0)));
translationAnimation.RepeatBehavior = RepeatBehavior.Forever;
Storyboard.SetTargetName(translationAnimation, "AnimatedTranslateTransform");
Storyboard.SetTargetProperty(translationAnimation, new PropertyPath(TranslateTransform.XProperty));
Storyboard translationStoryboard = new Storyboard();
translationStoryboard.Children.Add(translationAnimation);
translationStoryboard.Begin(this);
在这个示例中,一个共有3个关键帧:LinearDoubleKeyFrame,DiscreteDoubleKeyFrame,SplineDoubleKeyFrame。
LinearDoubleKeyFrame指的是:这是一个线性关键帧。
DiscreteDoubleKeyFrame指的是:这是一个离散关键帧。
SplineDoubleKeyFrame指的是:这是一个加速和减速关键帧。
要体会它们之间的差异,可以运行代码,任何语言描述不抵一次视觉感受。
3:动画缓动
缓动(Easing)允许我们创建各类动画效果,类似反弹或者弹簧效果。如BounceEase,模拟的就是一种弹跳效果。在第一个示例中,我们加入如下语句:
doubleAnimation.EasingFunction = new BounceEase() { Bounces=2, EasingMode = EasingMode.EaseOut, Bounciness = 2 };
就会发现图片在到达终点会弹跳,然后结束。所有内建的缓动类,都在System.Windows.Media.Animation命名空间中,它们都以Ease结尾。
本代码的源码下载:WpfApplication1.rar