65.9K
CodeProject 正在变化。 阅读更多。
Home

Silverlight 中的动画

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.91/5 (15投票s)

2010 年 6 月 9 日

CPOL

14分钟阅读

viewsIcon

98351

downloadIcon

3344

在本章中,您将学习 Silverlight 应用程序中动画的基本概念,包括动画类型、命名空间详细信息、类、使用的对象,以及使用 XAML 和 C# 代码实现不同类型的动画……

目录

  1. 概述
  2. Silverlight 动画简介
  3. 什么是 Silverlight 动画?
  4. Silverlight 动画使用的命名空间是什么?
  5. Timeline
  6. Silverlight 中动画的类型有哪些?
  7. 定义动画类型
  8. 什么是 Storyboard?
  9. Storyboard 属性
  10. Storyboard 方法
  11. 如何实现动画?
  12. 动画中使用的重要属性/方法有哪些?
    1. 持续时间
    2. BeginTime
    3. AutoReverse
    4. RepeatBehavior
    5. FillBehavior
    6. SpeedRatio
  13. 如何使用 XAML 触发 Storyboard Begin 事件?
  14. ColorAnimation 示例
  15. DoubleAnimation 示例
  16. PointAnimation 示例
  17. 后台代码动画示例
  18. XAML 中的动画与代码中的动画
  19. 开始、停止、暂停和恢复动画
  20. 结论
  21. 历史

概述

在本章中,您将学习 Silverlight 应用程序中动画的基本概念,包括动画类型、命名空间详细信息、类、使用的对象,以及使用 XAML 和 C# 代码实现不同类型的动画,以及更多有趣的示例。您将看到如何使用 `Timeline` 类的重要属性以及示例,并通过 `storyboard` 方法控制动画。我们还将通过示例介绍 XAML 中的动画与代码中的动画。

在本章结束时,您将学到:

  • 动画基本概念
  • 动画命名空间详细信息
  • 动画类型,如 from/to、关键帧和缓动函数
  • 如何在 Silverlight 中实现不同类型的动画
  • Storyboard 和动画类的重要属性和方法
  • XAML 中的动画与代码中的动画
  • 每种动画类型的示例

您还可以找到我关于 Silverlight 技术的其他文章

  1. Silverlight 简介 - ASilverlightIntroduction.aspx
  2. Silverlight 入门 - GettingStartedSilverlight.aspx
  3. Silverlight 数据绑定 - SLDataBindingIntro.aspx

Silverlight 动画简介

Silverlight 中的动画是自 Silverlight 技术初始发布以来就存在的一个令人兴奋的主题。在 Silverlight 的每个版本中,动画都有一些增强和性能改进。了解如何在 Silverlight 应用程序中应用动画非常重要,因为动画在大多数应用程序(如游戏、幻灯片等)中起着非常重要的作用。动画为用户界面带来了很好的效果。

什么是 Silverlight 动画?

在 Silverlight 应用程序中,我们可以通过在一段时间内应用对象的各个属性来对其进行动画处理。下面是一个简单的示例,演示如何在 500x500 的 Canvas 中将 `Path` 属性从 `From="50,450" To="450,50"` 改变。

图:四步动画演示

我们可以通过更改控件的高度、宽度、不透明度或颜色来应用动画。这里需要注意的重要一点是,我们只能对值类型为 double、color 和 point 的属性应用动画。

Silverlight 动画使用的命名空间是什么?

在 Silverlight 中,`System.Windows.Media.Animation` 命名空间提供了许多类和对象,有助于在 Silverlight 应用程序中执行动画。一些常用的类是 `Storyboard`、`ColorAnimation`、`DoubleAnimation`、`PointAnimation` 和 `Timeline`。

image006.jpg
图:MSDN 的动画命名空间截图

有关更多信息,请访问此链接

Timeline

所有动画类都继承自 `Timeline` 抽象类。`Timeline` 是基类 `abstract`,它提供了许多屏幕上突出显示的属性,我们将在后面的示例中使用它们。

图:动画或 Timeline 类属性

这里是继承自 `Timeline` 抽象类的 `Storyboard` 类的示例。

Silverlight 中动画的类型有哪些?

Silverlight 中的动画分为两类

图:Silverlight 中的动画类型
  1. From/To 动画:在开始值和结束值之间进行动画处理。创建动画时,我们将具有 `From` 和 `To` 属性来设置开始和结束值。
    • 使用 `From` 属性设置起始值
    • 使用 `To` 属性设置结束值

    这些动画易于实现,是基础动画。属于此类的动画是:

    1. ColorAnimation
    2. DoubleAnimation
    3. PointAnimation
  2. 关键帧动画:使用关键帧对象指定的系列值之间的动画处理。关键帧动画比 `From`/`To` 动画更强大,因为您可以指定任意数量的目标值,甚至可以控制它们的插值方法。这种动画实现比基本动画要复杂一些。属于此类的动画是:
    1. ColorAnimationUsingKeyFrames
    2. DoubleAnimationUsingKeyFrames
    3. PointAnimationUsingKeyFrames

定义动画类型

什么是 ColorAnimation?

对 Silverlight 控件的颜色属性应用动画称为 `ColorAnimation`。例如,`SolidColorBrush` 是颜色属性。

什么是 ColorAnimationUsingKeyFrames?

对 Silverlight 控件的颜色属性应用具有多个值的动画称为 `ColorAnimationUsingKeyFrames`。例如,`SolidColorBrush` 是颜色属性。

什么是 DoubleAnimation?

对 Silverlight 控件的整数或双精度值属性应用动画称为 `DoubleAnimation`。例如,`Opacity`、`Height` 或 `Width` 是双精度或整数值属性。

什么是 DoubleAnimationUsingKeyFrames?

对 Silverlight 控件的整数或双精度值属性应用具有多个值的动画称为 `DoubleAnimationUsingKeyFrames`。例如,`Opacity`、`Height` 或 `Width` 是双精度或整数值属性。

什么是 PointAnimation?

对 Silverlight 控件的点值属性应用动画称为 `PointAnimation`。例如,X、Y 坐标点。

什么是 PointAnimationUsingKeyFrames?

对 Silverlight 控件的点值属性应用具有多个值的动画称为 `PointAnimationUsingKeyFrames`。例如,X、Y 坐标点。

什么是 ObjectAnimationUsingKeyFrames?

对 Silverlight 控件的与对象相关的属性应用具有多个值的动画称为 `ObjectAnimationUsingKeyFrames`。例如,`Fill` 属性。

什么是 Storyboard?

`Storyboard` 类在 Silverlight 动画中起着非常重要的作用。没有 `storyboard` 类,我们就无法在 Silverlight 中实现动画。这是动画的核心部分,充当所有动画控件的父控件。它是包含一个或多个动画控件(如 `ColorAnimation`、`DoubleAnimation` 和 `PointAnimation` 等)的容器控件,并向动画控件发出播放动画的指令。如果您已经熟悉 `MediaElement` 控件,可以将其与该控件进行比较。`storyboard` 控件能够播放、暂停、恢复和停止动画。

`Storyboard` 类也继承自 `Timeline` 类。该类最重要的方面是其用于开始、停止、暂停和恢复动画的方法。

image013.jpg
图:动画控制 storyboard 方法

Storyboard 属性

  • `Storyboard` 的 `TartgetName` 和 `TargetProperty` 属性在定义 `storyboard` 时总是必需的,而且这两个属性易于理解。
  • `TargetName`:使用 `TargetName` 附加属性指定要为其设置动画的对象。
  • `TargetProperty`:使用 `TargetProperty` 附加属性指定要为其设置动画的属性。

让我们通过一个简单的例子来了解这两个属性的用法。在此示例中,我将目标设置为 `StackPanel` 控件进行动画处理。控件的名称 `MyStackPanel` 被分配给 `Storyboard.TargetName` 属性。

您会注意到,在此示例中,`Storyboard.TargetProperty` 的语法相当不同。

<StackPanel x:Name="myStackPanel" Background="Red"   Loaded="Start_Animation">
  <StackPanel.Resources>
    <Storyboard x:Name="colorStoryboard">
 
      <!-- Animate the background color of the canvas from red to green
        over 4 seconds. -->
      <ColorAnimation BeginTime="00:00:00" Storyboard.TargetName="myStackPanel" 
        Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)"
        From="Red" To="Green" Duration="0:0:4" />
 
    </Storyboard>
  </StackPanel.Resources>
</StackPanel>

请注意,正在设置动画的属性值(`Color`)属于一个 `SolidColorBrush` 对象,该对象既未命名也未显式声明。这种间接寻址是通过使用以下特殊语法实现的。

C#

Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)"

或者,您可以显式创建 `SolidColorBrush`,为其命名,并直接为其 `Color` 属性设置动画。以下示例展示了如何创建与上一个示例相同的动画,但使用了直接属性寻址。

<StackPanel Loaded="Start_Animation">
  <StackPanel.Resources>
    <Storyboard x:Name="colorStoryboard">
      <!-- Animate the background color of the canvas 
    from red to green over 4 seconds. -->
      <ColorAnimation BeginTime="00:00:00" Storyboard.TargetName="mySolidColorBrush"
        Storyboard.TargetProperty="Color" From="Red" To="Green" Duration="0:0:4" />
    </Storyboard>
  </StackPanel.Resources>
  <StackPanel.Background>
    <SolidColorBrush x:Name="mySolidColorBrush" Color="Red" />
  </StackPanel.Background>
</StackPanel>

注意:

为了在 `Storyboard` 中使用 `TargetName` 属性,您需要为目标控件赋予 `Name`。

Storyboard 方法

除了我们通过上述示例讨论的属性之外,`Storyboard` 类还支持一些方法,我们将在后台代码中经常使用它们来启动、停止、暂停和恢复。

  • `Begin`:使用 `storyboard` 中的第一个时间线开始动画
  • `Pause`:暂停当前 `storyboard` 的时间线。调用 `Resume` 来恢复时间线。
  • `Resume`:恢复当前 `storyboard` 的时间线
  • `Stop`:停止动画

如何实现动画?

在 Silverlight 中实现基本动画非常简单,只需四个步骤:

  1. 创建对象
  2. 创建动画
  3. 定义 Storyboard
  4. 将 Storyboard 与事件关联

为了讨论动画实现,让我们举一个简单的例子,一步一步地进行。

第一步:创建对象

第一步,您需要创建一个要为其设置动画的控件。在前面的示例中,我创建了一个简单的 `Ellipse` 控件,并将其放在 `Border` 控件中,以便它在边框内看起来不错。请确保您为要作为动画一部分进行更改的控件命名。

<Border x:Name="brdTest" BorderBrush="Green" 
    BorderThickness="4" Width="400" Height="400">

     <Ellipse Width="200" Height="200" >
            <Ellipse.Fill>
                <SolidColorBrush Color="Yellow" x:Name="myball">
                </SolidColorBrush>
            </Ellipse.Fill>
     </Ellipse>
</Border>

第二步:创建动画

创建 `ColorAnimation`、`DoubleAnimation`、`PointAnimation` 等动画类并设置其属性。在前面的示例中,我创建了一个 `ColorAnimation` 动画并设置了所需的属性。您需要确保在创建 `Animation` 类时设置了所需的属性,如 `Storyboard.TargetProperty`、`Storyboard.TargetName`、`From` 和 `To`。

<ColorAnimation     
    Storyboard.TargetProperty="Color" 
    Storyboard.TargetName="myball"
    From="Yellow"
    To="Green" />

第三步:定义 Storyboard

Silverlight 中的动画是通过使用 `Storyboard` 控件来实现的,该控件包含一个或多个子动画控件。`Storyboard` 的作用类似于具有播放、暂停和停止动画能力的 `MediaElement`。播放 `Storyboard` 时,动画控件会修改 Silverlight 控件的大小、形状和外观。

`Storyboard` 控件充当动画控件的容器控件,并允许您设置适用于动画的属性。`Storyboard` 控件最常用的属性是 `AutoReverse`、`BeginTime`、`RepeatBehavior` 和 `Duration`。

  <StackPanel.Resources>
            <Storyboard x:Name="mystoryboard" 
                AutoReverse="True" 
                Duration="0:0:5" >
                <ColorAnimation     
                    Storyboard.TargetProperty="Color" 
                    Storyboard.TargetName="myball"
                    From="Yellow"
                    To="Green" />
             </Storyboard>
</StackPanel.Resources>

注意:您必须将 `Storyboard` 控件创建为资源。

第四步:将 Storyboard 与事件关联

此时,您知道要为其设置动画的控件,也已创建了动画控件并为动画控件定义了 storyboard。那么一切都完成了,还有什么悬而未决?仅仅完成这三个步骤是不够的,我们还需要有一个触发器来启动动画。为此,您需要创建一个简单的按钮,并在托管代码中附加按钮单击事件。正如我们之前讨论的,storyboard 控件支持 `Begin()` 方法来启动动画。顺便说一句,您需要为 `Storyboard` 控件命名,以便在 C# 代码中访问它。

让我们来看看按钮控件和后台事件处理程序的操作。

<Button Content="Start" Click="Button_Click" Width="70" Height="30" 
    HorizontalAlignment="Center" />
private void Button_Click(object sender, RoutedEventArgs e)
{
       mystoryboard.Begin();
}

哇!我们知道了在 Silverlight 应用程序中创建基本动画的所有步骤。让我们将所有代码示例放在一起查看输出。在此示例中,矩形的颜色从黄色变为绿色。

XAML

<StackPanel>
    <StackPanel.Resources>
        <Storyboard x:Name="mystoryboard" 
            AutoReverse="True" 
            Duration="0:0:5" >
            <ColorAnimation     
                Storyboard.TargetProperty="Color" 
                Storyboard.TargetName="myball"
                From="Yellow"
                To="Green" />
        </Storyboard>
    </StackPanel.Resources>
 
    <Border x:Name="brdTest" BorderBrush="Green" BorderThickness="4" 
    Width="400" Height="400">
 
        <Ellipse Width="200" Height="200" >
            <Ellipse.Fill>
                <SolidColorBrush Color="Yellow" x:Name="myball">
                </SolidColorBrush>
            </Ellipse.Fill>
        </Ellipse>
    </Border>
    
    <Button Content="Start" Click="Button_Click" Width="70" 
    Height="30" HorizontalAlignment="Center" />
</StackPanel>

C#

private void Button_Click(object sender, RoutedEventArgs e)
{
    mystoryboard.Begin();
}

输出

图:Silverlight 中的第一个动画

动画中使用的重要属性/方法有哪些?

所有动画类都继承自 `Timeline` 基类,该类包含一些可供所有动画类使用的属性和方法。在继续举例之前,让我们先谈谈动画控件的属性。我上面重点介绍了一些 `Timeline` 类最重要的属性。

图:动画或 Timeline 类属性

`Duration`:`Duration` 属性允许您指定 `Storyboard` 播放所需的时间。`Duration` 的值基于 `hours:minutes:seconds` 语法。持续时间也可以在 `Storyboard` 中的每个动画控件上指定,而不是在 `Storyboard` 控件上。

`BeginTime`:`BeginTime` 属性指定 `Storyboard` 时间线中开始播放动画的时间,格式为 `hours:minutes:seconds`。

顾名思义,`BeginTime` 属性允许您指定动画对象开始活动的时间点。例如,您可以为 `Storyboard` 的 `BeginTime` 指定十秒钟的时间。当您使用 `Begin` 方法开始 `Storyboard` 时,`Storyboard` 将等待十秒钟然后开始。

让我们通过一个例子来理解 `BeginTime` 属性。在此示例中,持续时间为 20 秒,但 `BeginTime` 为 10 秒。但是,虽然 `Duration` 是 20 秒,但它不会动画 20 秒,而是由于延迟的 `BeginTime` 而只动画 10 秒。

图:理解 BeginTime 属性
<StackPanel Orientation="Vertical" >
            <StackPanel.Resources>
                <Storyboard BeginTime="0:0:10" x:Name="sbEllipse1">
                    <DoubleAnimation
                             Storyboard.TargetName="myBrush1"
                             Storyboard.TargetProperty="RadiusX"
                             From="0" To="1"
                             Duration="0:0:20"
                             />
                    <DoubleAnimation
                             Storyboard.TargetName="myBrush1"
                             Storyboard.TargetProperty="RadiusY"
                             From="0" To="1"
                             Duration="0:0:20"
                              />
                </Storyboard>
            </StackPanel.Resources>
            <Border x:Name="brdTest1" BorderBrush="Green" BorderThickness="4" 
        Width="300" Height="400">
        <Ellipse Height="100" Width="100">
            <Ellipse.Fill>
                <RadialGradientBrush x:Name="myBrush1"
                                  RadiusX="0.0"
                                  RadiusY="0.0"
                                 GradientOrigin="0.5,0.5">
                    <GradientStop Color="Red" Offset="0.25"/>
                    <GradientStop Color="Green" Offset="0.50"/>
                    <GradientStop Color="Yellow" Offset="0.75"/>
                    <GradientStop Color="Blue" Offset="1.0"/>
                </RadialGradientBrush>
            </Ellipse.Fill>
        </Ellipse>
    </Border>
    <Button Content="Start" Click="Button1_Click" Width="70" 
    Height="30" HorizontalAlignment="Center" />
  </StackPanel>
private void Button1_Click(object sender, RoutedEventArgs e)
{
    sbEllipse1.Begin();
}

图:BeginTime 属性示例

`AutoReverse`:如果 `AutoReverse` 属性设置为 `True`,则动画首先向前播放,然后立即向后播放。这允许您将 Silverlight 控件恢复到其原始状态。这在实现仅在鼠标悬停在控件上时为其设置动画的动画时非常有用。

<StackPanel.Resources>
    <Storyboard BeginTime="0:0:0" x:Name="sbEllipse2" AutoReverse="True">
        <DoubleAnimation
                 Storyboard.TargetName="myBrush2"
                 Storyboard.TargetProperty="RadiusX"
                 From="0" To="1"
                 Duration="0:0:10"
                 />
        <DoubleAnimation
                 Storyboard.TargetName="myBrush2"
                 Storyboard.TargetProperty="RadiusY"
                 From="0" To="1"
                 Duration="0:0:10"
                  />
    </Storyboard>
</StackPanel.Resources>

图:AutoReverse 属性示例输出

`RepeatBehavior`:`RepeatBehavior` 属性允许您指定重复动画的次数。如果您希望动画无限期运行,可以将 `RepeatBehavior` 属性设置为 `Forever`。如果 `AutoReverse` 设置为 `True`,则向前和向后播放仅计为一个迭代。例如,以下 `Storyboard` 代码重复动画三次。

基本上,RepeatBehavior 可以定义为:

Ø  Timespan string RepeatBehavior="0:0:4"
Ø  #x string RepeatBehavior="2x" 
Ø  special value Forever RepeatBehavior="Forever"

这是 `RepeatBehavior` 属性使用方式的示例。

<!--RepeatBehavior-->
<StackPanel>
    <StackPanel.Resources>
        <Storyboard x:Name="myStoryboard">
            <!-- Create an animation that repeats indefinitely. -->
            <DoubleAnimation 
              Storyboard.TargetName="ForeverRepeatingRectangle" 
              Storyboard.TargetProperty="Width" 
              From="50" To="300" Duration="0:0:2" RepeatBehavior="Forever" />
 
            <!-- Create an animation that repeats for four seconds. As a result, the
         animation repeats twice. -->
            <DoubleAnimation 
              Storyboard.TargetName="FourSecondsRepeatingRectangle" 
              Storyboard.TargetProperty="Width"
              From="50" To="300" Duration="0:0:2" RepeatBehavior="0:0:4" />
 
            <!-- Create an animation that repeats twice. -->
            <DoubleAnimation 
              Storyboard.TargetName="TwiceRepeatingRectangle" 
              Storyboard.TargetProperty="Width" 
              From="50" To="300" Duration="0:0:2" RepeatBehavior="2x" />
 
            <!-- Create an animation that repeats 0.5 times. The resulting animation
         plays for one second, half of its Duration. It animates from 50 to 150. -->
            <DoubleAnimation 
              Storyboard.TargetName="HalfRepeatingRectangle" 
              Storyboard.TargetProperty="Width" 
              From="50" To="300" Duration="0:0:2" RepeatBehavior="0.5x" />
 
            <!-- Create an animation that repeats for one second. The resulting animation
         plays for one second, half of its Duration. It animates from 50 to 150. -->
            <DoubleAnimation 
              Storyboard.TargetName="OneSecondRepeatingRectangle" 
              Storyboard.TargetProperty="Width" 
              From="50" To="300" Duration="0:0:2" RepeatBehavior="0:0:1" />
        </Storyboard>
    </StackPanel.Resources>
        <TextBlock Text="RepeatBehavior Property" />
        <Border x:Name="brdTest4" BorderBrush="Green" BorderThickness="4" 
    Width="300" Height="400">
        <StackPanel>
                    <!-- Create several rectangles to animate. -->
        <Rectangle Name="ForeverRepeatingRectangle" 
            Fill="Red" Width="50" Height="20" />
        <Rectangle Name="FourSecondsRepeatingRectangle" 
            Fill="Blue" Width="50" Height="20" />
        <Rectangle Name="TwiceRepeatingRectangle" 
         Fill="Yellow" Width="50" Height="20" />
        <Rectangle Name="HalfRepeatingRectangle" 
            Fill="Green" Width="50" Height="20" />
        <Rectangle Name="OneSecondRepeatingRectangle" 
            Fill="Orange" Width="50" Height="20" />
     </StackPanel>
    <!-- Create buttons to restart and stop the animations. -->
    </Border>
    <Button Margin="10" Content="Restart Animation" Click="Start_Animation" />
 
</StackPanel>
private void Start_Animation(object sender, RoutedEventArgs e)
{
    myStoryboard.Begin();
}
图:RepeatBehavior 属性示例输出

`FillBehavior`:`FillBehavior` 属性指定时间线结束时的行为。此属性的默认值是 `HoldEnd`,这意味着在动画结束后,被动画化的对象将保持其最终值。例如,如果您在 2 秒内将 `Rectangle` 的 `Opacity` 属性从 1 动画到 0,默认行为是在 2 秒结束后,矩形将保持 0 不透明度。如果将 `FillBehavior` 设置为 `Stop`,则在动画结束后,矩形的不透明度将恢复到其原始值 1。

查看 Visual Studio 2008 中的智能感知

<!--FillBehavior Property-->
<StackPanel>
        <TextBlock Text="FillBehavior Property" />
        <Border x:Name="brdTest5" BorderBrush="Green" 
        BorderThickness="4" Width="300" Height="400">
        <Rectangle
            x:Name="MyAnimatedRectangle"
            Width="100"
            Height="100"
            Fill="Blue">
        <Rectangle.Triggers>
            <!-- Animates the rectangle's opacity. -->
            <EventTrigger RoutedEvent="Rectangle.Loaded">
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation
                          Storyboard.TargetName="MyAnimatedRectangle"
                          Storyboard.TargetProperty="Opacity"
                          From="1.0" To="0" Duration="0:0:10" FillBehavior="HoldEnd"  />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Rectangle.Triggers>
      </Rectangle>
    </Border>
</StackPanel>

`SpeedRatio`:这指定当前时间线相对于其父级流逝的时间速率。默认值为 1。

让我们详细了解 `SpeedRatio` 属性。如果 `SpeedRatio` 设置为 3,则动画完成速度提高三倍。如果降低它,动画会变慢(例如,如果 `SpeedRatio` 设置为 0.5,则动画需要两倍的时间)。虽然整体效果与更改动画的 `Duration` 属性相同,但设置 `SpeedRatio` 可以更轻松地控制同时动画的重叠方式。

以下快照描述了 `from/to` 类型的 `DoubleAnimation`,其中 `SpeedRatio` 属性设置为 2。这将导致 `Image1 Image` 控件的淡入效果在 0.5 秒内完成。

<Storyboard x:Name="fadeIn">
    <DoubleAnimation From="0" To="1"
        Storyboard.TargetName="Image1"
        Storyboard.TargetProperty="Opacity"
        SpeedRatio="2">
     </DoubleAnimation>
</Storyboard>

默认值:如果您在动画或 storyboard 中不使用任何属性,它将使用属性的默认值,动画只播放一次。

<StackPanel.Resources>
    <Storyboard x:Name="sbEllipse1">
        <DoubleAnimation
                     Storyboard.TargetName="myBrush1"
                     Storyboard.TargetProperty="RadiusX"
                     From="0" To="1"                     
                     />
        <DoubleAnimation
                     Storyboard.TargetName="myBrush1"
                     Storyboard.TargetProperty="RadiusY"
                     From="0" To="1"/>
    </Storyboard>
</StackPanel.Resources>

以上所有属性的实际输出

图:动画属性的实际应用

如何使用 XAML 触发 Storyboard Begin 事件?

当您开始在 Silverlight 应用程序中实现动画时,您会发现其中一些应该由托管代码启动。但是,有些动画应该在应用程序加载后立即开始。

可以通过将 `Storyboard` 控件嵌套在根布局控件的 `EventTrigger` 元素中,从而在页面加载时启动动画。以下代码展示了将 `Storyboard` 控件嵌套在 `Grid` 控件的 `EventTrigger` 元素中的示例。

<Grid x:Name="LayoutRoot" Background="White">
        <Grid.Triggers>
            <EventTrigger RoutedEvent="Grid.Loaded">
                <TriggerActionCollection>
                    <BeginStoryboard>
                        <Storyboard AutoReverse="True" RepeatBehavior="Forever">
                            <PointAnimation To="50,350" Storyboard.TargetName="line4" 
                Storyboard.TargetProperty="EndPoint" />
                        </Storyboard>
                    </BeginStoryboard>
                </TriggerActionCollection>
            </EventTrigger>
        </Grid.Triggers>
        <Border x:Name="brdTest" BorderBrush="Green" BorderThickness="4" 
        Width="400" Height="400">
            <Path Stroke="Black" StrokeThickness="1">
            <Path.Data>
                <GeometryGroup>
                    <LineGeometry x:Name="line4" StartPoint="100,150" 
            EndPoint="200,250" />
                </GeometryGroup>
            </Path.Data>
        </Path>
        </Border>
   </Grid>

`EventTrigger` 将 `Loaded` 事件附加到 `Grid` 元素,然后在 `TriggerActionCollection` 中定义 `BeginStoryboard` 元素。

ColorAnimation 示例

<StackPanel Orientation="Vertical">
    <StackPanel.Resources>
        <Storyboard x:Name="mystoryboard" 
            AutoReverse="True" 
            Duration="0:0:5" >
            <ColorAnimation     
                Storyboard.TargetProperty="Color" 
                Storyboard.TargetName="myball"
                From="Yellow"
                To="Green" />
         </Storyboard>
    </StackPanel.Resources>
    <Border x:Name="brdTest" BorderBrush="Green" BorderThickness="4" 
    Width="400" Height="400">
 
        <Ellipse Width="200" Height="200" >
        <Ellipse.Fill>
            <SolidColorBrush Color="Yellow" x:Name="myball">
            </SolidColorBrush>
        </Ellipse.Fill>
    </Ellipse>
    </Border>
    <Button Content="Start" Click="Button_Click" Width="70" 
    Height="30" HorizontalAlignment="Center" />
 
</StackPanel>

C#

private void Button_Click(object sender, RoutedEventArgs e)
{
    mystoryboard.Begin();
}

DoubleAnimation 示例

XAML

<StackPanel Orientation="Vertical">
    <StackPanel.Resources>
        <Storyboard BeginTime="0:0:0" x:Name="sbEllipse" Duration="Forever">
                        <DoubleAnimation
                             Storyboard.TargetName="myBrush"
                             Storyboard.TargetProperty="RadiusX"
                             From="0" To="1"
                             Duration="0:0:5"
                             AutoReverse="True" />
                        <DoubleAnimation
                             Storyboard.TargetName="myBrush"
                             Storyboard.TargetProperty="RadiusY"
                             From="0" To="1"
                             Duration="0:0:5"
                             AutoReverse="True" />
                    </Storyboard>
   </StackPanel.Resources>
    <Border x:Name="brdTest" BorderBrush="Green" BorderThickness="4" 
    Width="400" Height="400">
 
        <Ellipse Height="250" Width="250">
                <Ellipse.Fill>
                    <RadialGradientBrush x:Name="myBrush"
                                      RadiusX="0.0"
                                      RadiusY="0.0"
                                     GradientOrigin="0.5,0.8">
                        <GradientStop Color="Red" Offset="0.0"/>
                        <GradientStop Color="Blue" Offset="0.25"/>
                        <GradientStop Color="Yellow" Offset="0.5"/>
                        <GradientStop Color="Green" Offset="1.0"/>
                    </RadialGradientBrush>
                </Ellipse.Fill>
    </Ellipse>
    </Border>

    <Button Content="Start" Click="Button_Click" Width="70" 
    Height="30" HorizontalAlignment="Center" />
</StackPanel>

C#

private void Button_Click(object sender, RoutedEventArgs e)
{
    sbEllipse.Begin();
}

PointAnimation 示例

XAML

<Canvas Width="500" Height="500">
        <Canvas.Resources>
            <Storyboard x:Name="myStoryboard">
                <!-- Animate the center point of the ellipse from 0 X, 
        500 Y to 500 X, 0 Y over 5 seconds. -->
                <PointAnimation
                     Storyboard.TargetProperty="Center"
                     Storyboard.TargetName="MyAnimatedEllipseGeometry"
                     Duration="0:0:5" 
                     From="50,450"
                     To="450,50"
                     RepeatBehavior="Forever" />
            </Storyboard>
        </Canvas.Resources>
        <Border x:Name="brdTest" BorderBrush="Green" BorderThickness="4" 
        Width="500" Height="500">
        
            <Path Fill="Red" Loaded="Start_Animation">
                <Path.Data>
                    <!-- Describes an ellipse. -->
                    <EllipseGeometry x:Name="MyAnimatedEllipseGeometry" 
            Center="200,100" RadiusX="35" RadiusY="35" />
                </Path.Data>
                <!--<Path.Fill>
                    <RadialGradientBrush x:Name="myBrush"
                                          RadiusX="35"
                                          RadiusY="35"
                                         GradientOrigin="0.5,0.5">
                        <GradientStop Color="Red" Offset="0.0"/>
                        <GradientStop Color="Blue" Offset="0.25"/>
                        <GradientStop Color="Yellow" Offset="0.5"/>
                        <GradientStop Color="Green" Offset="1.0"/>
                    </RadialGradientBrush>
                </Path.Fill>-->
            </Path>
        </Border>    
    </Canvas>

C#

private void Start_Animation(object sender, RoutedEventArgs e)
{
    myStoryboard.Begin();
}

后台代码动画示例

<Canvas x:Name="LayoutRoot" Background="White">

</Canvas>
public partial class AnimationWithCSharp : UserControl
    {
        public AnimationWithCSharp()
        {
            InitializeComponent();
            Loaded += new RoutedEventHandler(MainPage_Loaded);
        }
 
        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            //Create Ellipse that will be targeted for animation here
 
            Ellipse myEllipse = new Ellipse();
            myEllipse.Width = 100;
            myEllipse.Height = 100;
 
            //Create the RadialGradientBrush here
            RadialGradientBrush myrgBrush = new RadialGradientBrush();
            Point mypoint = new Point(0.5, 0.5);
            myrgBrush.GradientOrigin = mypoint;//Method 1
            myrgBrush.Center = new Point(0.5, 0.5);//Method 2
            myrgBrush.RadiusX = 0.5;
            myrgBrush.RadiusY = 0.5;
 
            GradientStop gStop1 = new GradientStop();
            gStop1.Color = Colors.Red;//Method 1 
            gStop1.Offset = 0.0;
            myrgBrush.GradientStops.Add(gStop1);
 
            GradientStop gStop2 = new GradientStop();
            gStop2.Color = Color.FromArgb(255, 0, 255, 0);//Method 2
            gStop2.Offset = 0.5;
            myrgBrush.GradientStops.Add(gStop2);
 
            GradientStop gStop3 = new GradientStop();
            gStop3.Color = Colors.Blue;
            gStop3.Offset = 1;
            myrgBrush.GradientStops.Add(gStop3);
 
            myEllipse.Fill = myrgBrush;
            // Add the Ellipse to the tree.
            LayoutRoot.Children.Add(myEllipse);
 
            // Create a duration of 5 seconds.
            Duration duration = new Duration(TimeSpan.FromSeconds(5));
 
            // Create two DoubleAnimations and set their properties.
            DoubleAnimation myDoubleAnimation1 = new DoubleAnimation();
            DoubleAnimation myDoubleAnimation2 = new DoubleAnimation();
 
            myDoubleAnimation1.Duration = duration;
            myDoubleAnimation2.Duration = duration;
 
            Storyboard sb = new Storyboard();
            sb.Duration = duration;
 
 
            sb.Children.Add(myDoubleAnimation1);
            sb.Children.Add(myDoubleAnimation2);
 
            Storyboard.SetTarget(myDoubleAnimation1, myEllipse);
            Storyboard.SetTarget(myDoubleAnimation2, myEllipse);
 
            // Set the attached properties of Canvas.Left and Canvas.Top
            // to be the target properties of the two respective DoubleAnimations.
            Storyboard.SetTargetProperty
        (myDoubleAnimation1, new PropertyPath("(Canvas.Left)"));
            Storyboard.SetTargetProperty
        (myDoubleAnimation2, new PropertyPath("(Canvas.Top)"));
 
            myDoubleAnimation1.To = 200;
            myDoubleAnimation2.To = 200;
            // Make the Storyboard a resource.
            LayoutRoot.Resources.Add("unique_id", sb);
 
            // Begin the animation.
            sb.Begin(); 
        }       
    }

XAML 中的动画与代码中的动画

了解何时使用 XAML 以及何时使用后台代码实现 Silverlight 动画非常重要。考虑到应用程序的性能,我们需要进行尝试。

在 XAML 中定义 `storyboard` 和 `Timeline` 通常更容易实现,并且在大多数情况下是首选方法。但有时它很耗时且工作量很大,在这种情况下,我们可能需要在后端 C#/VB.NET 代码中实现 storyboard 和 timelines,而不是使用 XAML。

在前面的示例中,当鼠标悬停在网格单元格上时,我们需要更改网格单元格颜色的不透明度。为了满足此要求,我们可以使用 XAML,但需要编写大量代码来定义 storyboards 和 timelines,而使用代码只需不到 50 行。

namespace AnimationSampleCode
{
    public partial class AnimationWithCSharp : UserControl
    {
        public AnimationWithCSharp()
        {
            InitializeComponent();
            
            //Load simple animation using code behind
            //Loaded += new RoutedEventHandler(MainPage_Loaded);
            
            //Calling Load Color Method here
            LoadColors();
        } 
        
        //Declare page level variables
        private Random _random = new Random((int)DateTime.Now.Ticks);
        private TimeSpan _halfSecond = new TimeSpan(0, 0, 0,0,  500);     
 
        private void LoadColors()
        {
            //create grid cells dynamically
            int gridsize = 15;
            for (int i = 0; i < gridsize;i++ )
            {
                gridColors.RowDefinitions.Add(new RowDefinition());
                gridColors.ColumnDefinitions.Add(new ColumnDefinition());
            }
 
            for (int col = 0; col < gridsize; col++)
            {
                for (int row = 0; row < gridsize; row++)
                {
                    //Create rectangles and add it to grid cells
                    Rectangle rect = new Rectangle()
                    {
                        Margin = new Thickness(2),
                        Fill = RandomColor(),
                        Opacity = .05
                    };
                     Grid.SetColumn(rect,col);
                    Grid.SetRow(rect,row);
 
                    Storyboard mouseOverAnimation = new Storyboard();
                    DoubleAnimation newAnim = new DoubleAnimation()
                    {
                        To = 10,
                        Duration = _halfSecond ,
                        AutoReverse =true
                    };
 
                    mouseOverAnimation.Children.Add(newAnim);
                        Storyboard.SetTarget(newAnim,rect);
                    Storyboard.SetTargetProperty(newAnim,new PropertyPath("Opacity"));
                    //Event handler
                    rect.MouseEnter += delegate(object sender, MouseEventArgs e)
                    {
                        mouseOverAnimation.Begin();
                    };
 
                    gridColors.Children.Add(rect);
                }
            }
        }
        //Helper function 
        private SolidColorBrush RandomColor()
        {
            byte[] rgb = new byte[3];
            _random.NextBytes(rgb);
            Color randomColor = Color.FromArgb(255, rgb[0], rgb[1], rgb[2]);
            return new SolidColorBrush(randomColor);
        }
    }
 
   }

开始、停止、暂停和恢复动画示例

动画必须使用 Storyboard 的 `begin()` 方法启动。一旦动画开始,您就可以停止或暂停,然后暂停的动画可以恢复。

<!--Storyboard Methods-->
<StackPanel Orientation="Vertical" HorizontalAlignment="Left">
    <StackPanel.Resources>
        <Storyboard BeginTime="0:0:0" x:Name="sbEllipse" AutoReverse="True" >
            <DoubleAnimation
                 Storyboard.TargetName="myBrush"
                 Storyboard.TargetProperty="RadiusX"
                 From="0" To="1"
                 Duration="0:0:10" 
                 />
            <DoubleAnimation
                 Storyboard.TargetName="myBrush"
                 Storyboard.TargetProperty="RadiusY"
                 From="0" To="1"
                 Duration="0:0:10"
                  />
        </Storyboard>
    </StackPanel.Resources>
 
    <TextBlock Text="Storyboard Methods" />
    <Border x:Name="brdTest" BorderBrush="Green" 
        BorderThickness="4" Width="300" Height="400">
        <Ellipse Height="100" Width="100">
            <Ellipse.Fill>
                <RadialGradientBrush x:Name="myBrush"
                              RadiusX="0.5"
                              RadiusY="0.5"
                             GradientOrigin="0.5,0.5">
                    <GradientStop Color="Red" Offset="0.25"/>
                    <GradientStop Color="Blue" Offset="0.50"/>
                    <GradientStop Color="Yellow" Offset="0.75"/>
                    <GradientStop Color="Green" Offset="1.0"/>
                </RadialGradientBrush>
            </Ellipse.Fill>
        </Ellipse>
    </Border>
    <StackPanel Orientation="Horizontal">
 
        <Button Content="Start" Click="ButtonStart_Click" 
        Width="70" Height="30" HorizontalAlignment="Center" />
    <Button Content="Pause" Click="ButtonPause_Click" 
    Width="70" Height="30" HorizontalAlignment="Center" />
 
    <Button Content="Resume" Click="ButtonResume_Click" 
    Width="70" Height="30" HorizontalAlignment="Center" />
    <Button Content="Stop" Click="ButtonStop_Click" 
    Width="70" Height="30" HorizontalAlignment="Center" />
</StackPanel>
</StackPanel>

C#

private void ButtonStart_Click(object sender, RoutedEventArgs e)
{
    sbEllipse.Begin();
}

private void ButtonPause_Click(object sender, RoutedEventArgs e)
{
    sbEllipse.Pause();
}
 
private void ButtonResume_Click(object sender, RoutedEventArgs e)
{
    sbEllipse.Resume();
}
 
private void ButtonStop_Click(object sender, RoutedEventArgs e)
{
    sbEllipse.Stop();
}

结论

希望您喜欢本章,请不要忘记写下您对本章的评论,这将帮助我将来改进自己。

历史

  • 2010 年 6 月 7 日:初版
© . All rights reserved.