本篇介绍动画(Animation)的内容。
处理动画的命名空间主要为:System.Windows.Media.Animation
主要类的继承层次为:
System.Object
System.Windows.DependencyObject
System.Windows.Media.Animation.Timeline
System.Windows.Media.Animation.ColorAnimation
System.Windows.Media.Animation.ColorAnimationUsingKeyFrames
System.Windows.Media.Animation.DoubleAnimation
System.Windows.Media.Animation.DoubleAnimationUsingKeyFrames
System.Windows.Media.Animation.ObjectAnimationUsingKeyFrames
System.Windows.Media.Animation.PointAnimation
System.Windows.Media.Animation.PointAnimationUsingKeyFrames
System.Windows.Media.Animation.Storyboard
可见这些类都继承自时间线又称时间轴(Timeline)。
还有些不是继承自时间线的其他类,后面详细介绍。
BeginStoryboard
BeginStoryboard是一个触发器操作,该操作启动 Storyboard 进行动画处理。
XAML:
<Ellipse x:Name="e" Stroke="Red" Fill="Yellow" Width="200" Height="100">
<Ellipse.Triggers>
<EventTrigger RoutedEvent="Ellipse.Loaded">
<BeginStoryboard>
<Storyboard>
...
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Ellipse.Triggers>
</Ellipse>
椭圆Loaded完成即触发启动Storyboard。
Storyboard
为容器的子动画提供对象和属性目标信息的容器时间线。这是动画处理中最重要的类之一。
它有Begin()、Pause()、Resume()、Stop()等方法,可以对动画进行控制;有AutoReverse、Duration等属性来设置动画的行为。
<Storyboard>
...
</Storyboard>
Color相关的动画类
System.Object
System.Windows.DependencyObject
System.Windows.Media.Animation.Timeline
System.Windows.Media.Animation.ColorAnimation
System.Windows.Media.Animation.Timeline
System.Windows.Media.Animation.ColorAnimationUsingKeyFrames
System.Windows.Media.Animation.ColorKeyFrame
System.Windows.Media.Animation.DiscreteColorKeyFrame
System.Windows.Media.Animation.LinearColorKeyFrame
System.Windows.Media.Animation.SplineColorKeyFrame
System.Windows.PresentationFrameworkCollection<ColorKeyFrame>
System.Windows.Media.Animation.ColorKeyFrameCollection
XAML:
<Ellipse x:Name="e" Stroke="Red" Fill="Yellow" Width="200" Height="100">
<Ellipse.Triggers>
<EventTrigger RoutedEvent="Ellipse.Loaded">
<BeginStoryboard>
<Storyboard>
<ColorAnimation BeginTime="0:0:0" Storyboard.TargetName="e"
Storyboard.TargetProperty="(Ellipse.Fill).(SolidColorBrush.Color)"
From="Yellow" To="White" Duration="0:0:2" AutoReverse="True"
RepeatBehavior="Forever" >
</ColorAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Ellipse.Triggers>
</Ellipse>
ColorAnimation:在指定的 Duration 内使用线性内插对两个目标值之间的 Color 属性值进行动画处理。
Storyboard.TargetName:设置要进行动画处理的元素。
Storyboard.TargetProperty:设置要进行动画处理的元素的属性。
From:动画处理的基值。
To:动画处理的目标值。
By:动画处理的目标值为From值和By值的和,当To和By值同时存在时,忽略By值。
Duration:动画从基值到目标值过渡的时间。
AutoReverse:获取或设置一个值,该值指示时间线在完成向前迭代后是否按相反的顺序播放。
RepeatBehavior:获取或设置此时间线的重复行为。一个迭代 Count,指定时间线将要播放的次数;一个 TimeSpan 值,指定此时间线活动周期的总长度;或者特殊值 Forever,指定时间线应该无限重复。默认值是 RepeatBehavior 的 Count 为 1,该值指示时间线播放一次。
ColorAnimationUsingKeyFrames:对指定 Duration 内的一组 KeyFrames 中的 Color 属性值进行动画处理。
关键帧动画的目标值是通过其 KeyFrames 属性定义的,该属性包含 ColorKeyFrame 对象的集合。每个 ColorKeyFrame 都定义一段动画及其自己的目标 Value 和 KeyTime。动画运行时,它将在指定的关键时间从一个关键值移动到下一个关键值。
与 ColorAnimation 不同,ColorAnimationUsingKeyFrames 可以有两个以上的目标值。您还可以控制单个 ColorKeyFrame 段的内插方法。
ColorKeyFrame:有三种类型,分别对应一个支持的内插方法:LinearColorKeyFrame、DiscreteColorKeyFrame 和 SplineColorKeyFrame。
LinearColorKeyFrame:线性内插,基值与目标值平滑过渡。
DiscreteColorKeyFrame:离散内插,到达Duration结束时间点时突然跳跃到目标值。
SplineColorKeyFrame:样条内插,通过设置KeySpline属性,设置两个控制点来控制基值到目标值过渡的快慢,有利于模拟自然界的运动,其原理类似与前面介绍的三次贝塞尔曲线,具体算法可查相关资料。
Double相关的动画和Point相关的动画跟上面Color相关的动画极其相似,使用时可查阅MSDN,在此不多介绍。
示例:刺破气泡的小游戏
XAML:
<Canvas x:Name="LayoutRoot">
<Canvas.Resources>
<Storyboard x:Name="sbMove" Storyboard.TargetName="position"
Storyboard.TargetProperty="Center">
<PointAnimationUsingKeyFrames>
<SplinePointKeyFrame x:Name="spFrame" KeyTime="0:0:0.01"
KeySpline="0.6,0.0 0.9,0.0">
</SplinePointKeyFrame>
<LinearPointKeyFrame x:Name="lnFrame" KeyTime="0:0:0.02">
</LinearPointKeyFrame>
<DiscretePointKeyFrame x:Name="dsFrame" KeyTime="0:0:0.02">
</DiscretePointKeyFrame>
</PointAnimationUsingKeyFrames>
</Storyboard>
</Canvas.Resources>
<Canvas.Background>
<ImageBrush ImageSource="1.jpg"></ImageBrush>
</Canvas.Background>
<TextBlock Canvas.Left="20" Text="数量:"
Foreground="Yellow" FontSize="20"></TextBlock>
<TextBlock x:Name="count" Canvas.Left="80" Text="0"
Foreground="Yellow" FontSize="20"></TextBlock>
<Button x:Name="btnFull" Width="80" Height="30"
Foreground="Black" Content="全屏" Canvas.ZIndex="10"
Click="btnFull_Click" Canvas.Left="120"></Button>
<Path x:Name="bubble" Canvas.ZIndex="5"
Stroke="Transparent" MouseEnter="bubble_MouseEnter">
<Path.Fill>
<RadialGradientBrush>
<GradientStop Color="Transparent" Offset="0.7"></GradientStop>
<GradientStop Color="White" Offset="1.0"></GradientStop>
</RadialGradientBrush>
</Path.Fill>
<Path.Data>
<EllipseGeometry x:Name="position" RadiusX="20"
RadiusY="20" Center="20,20"></EllipseGeometry>
</Path.Data>
<Path.Triggers>
<EventTrigger RoutedEvent="Path.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="bubble" Storyboard.TargetProperty="Opacity"
From="1.0" To="0.5" Duration="0:0:0.5" RepeatBehavior="Forever">
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Path.Triggers>
</Path>
<Image x:Name="pointer" Canvas.ZIndex="6" Source="2.png" Width="30" Height="27"></Image>
</Canvas>
C#:
{
Random rnd = new Random();
int top = 0;
int left = 0;
int height = 600;
int width = 800;
DispatcherTimer timer = new DispatcherTimer();
public Page()
{
InitializeComponent();
this.Cursor = Cursors.None;
timer.Interval = new TimeSpan(0, 1, 0);
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
timer.Stop();
if (Convert.ToInt32(count.Text) > 10)
{
HtmlPage.Window.Alert("你一分钟刺破气泡的数目为:" + count.Text + " ,继续努力^_^");
}
count.Text = "0";
timer.Start();
}
private void bubble_MouseEnter(object sender, MouseEventArgs e)
{
top = rnd.Next(20, width - 20);
left = rnd.Next(20, height - 40);
spFrame.Value = new Point(position.Center.X, top);
lnFrame.Value = new Point(left / 2, top);
dsFrame.Value = new Point(left, top);
sbMove.Begin();
count.Text = (Convert.ToInt32(count.Text) + 1).ToString();
}
private void LayoutRoot_MouseMove(object sender, MouseEventArgs e)
{
Canvas.SetLeft(pointer, e.GetPosition(this).X);
Canvas.SetTop(pointer, e.GetPosition(this).Y);
}
private void btnFull_Click(object sender, RoutedEventArgs e)
{
Content contentObject = Application.Current.Host.Content;
contentObject.IsFullScreen = !contentObject.IsFullScreen;
}
}
ObjectAnimationUsingKeyFrames
ObjectAnimationUsingKeyFrames动画相关的类与上面介绍的类似,对指定 Duration 内的一组 KeyFrames 中的 Object 属性值进行动画处理。
它的Storyboard.TargetProperty属性可以对背景、填充等复杂属性进行动画处理。
结束语
动画处理是Silverlight非常吸引人的一个部分,可以用来实现实验演示、MV、广告等。