微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

以编程方式使用动画


Silverlight
4(共 4)对本文的评价是有帮助 - 评价此主题

有时您可能要动态(即时)更改动画的属性 例如,您可能要调整应用到对象的动画行为,这取决于对象当前在布局中的位置、对象包含何种内容等等。 可以通过使用程序代码(例如 C# 或 Visual Basic)动态操作动画。

主题包括下列各节。

您应熟悉 Silverlight 动画。 有关简介,请参见动画概述

访问动画对象以更改其属性的最直接方法是:命名该动画对象,然后在代码中通过该名称引用它。 下面的示例包含一个 Ellipse,当您在屏幕上单击时它将显示动画效果 为了实现此动画,在单击 Canvas 时,事件处理程序更改 PointAnimation 对象的 To 属性,然后启动动画。

运行此示例

<CanvasMouseLeftButtonDown="Handle_MouseDown"Background="Gray"Width="600"Height="500"><Canvas.Resources><Storyboardx:Name="myStoryboard"><!-- The PointAnimation has a name so it can be accessed
             from code. The To property is left out of the XAML
             because the value of To is determined in code. --><PointAnimationx:Name="myPointAnimation"Storyboard.TargetProperty="Center"Storyboard.TargetName="MyAnimatedEllipseGeometry"Duration="0:0:2"/></Storyboard></PathFill="Blue"><Path.Data><!-- Describes an ellipse. --><EllipseGeometryx:Name="MyAnimatedEllipseGeometry"Center="200,100"RadiusX="15"RadiusY="15"/></Path.Data></Path></Canvas>
C#
VB
privatevoid Handle_MouseDown(object sender,MouseButtonEventArgs e)
{
    // Retrieve current mouse coordinates.double newX = e.GetPosition(null).X;
    double newY = e.GetPosition(null).Y;
    Point myPoint = new Point();
    myPoint.X = newX;
    myPoint.Y = newY;
    myPointAnimation.To = myPoint;
    myStoryboard.Begin();
}


使所有动画具有唯一的名称有时不易做到。 这时您可以使用集合来访问动画或动画的关键帧。 例如,如果要以编程方式访问 DoubleAnimationUsingKeyFrames 对象中的所有关键帧,可以使用与以下代码类似的代码

Canvas x:Name="parentCanvas" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  Width="600" Height="500" Background="Gray">
  <Canvas.Resources>
    <Storyboard x:Name="myStoryboard">
      <PointAnimationUsingKeyFrames
        x:Name="myPointAnimationUsingKeyFrames"
        Storyboard.TargetProperty="Center"
        Storyboard.TargetName="MyAnimatedEllipseGeometry"
        Duration="0:0:3">

          <!-- Set of keyframes -->
          <discretePointKeyFrame KeyTime="0:0:0" />
          <LinearPointKeyFrame KeyTime="0:0:0.5" />
          <SplinePointKeyFrame KeySpline="0.6,0.0 0.9,0.00" KeyTime="0:0:3" />
      </PointAnimationUsingKeyFrames>
    </Storyboard>

  </Canvas.Resources>

  <Path Fill="Blue">
    <Path.Data>

      <!-- Describes an ellipse. -->
      <EllipseGeometry x:Name="MyAnimatedEllipseGeometry"
        Center="200,100" RadiusX="15" RadiusY="15" />
    </Path.Data>
  </Path>
</Canvas>
C#
public void Handle_MouseDown(object sender,MouseEventArgs e)
{
    int i;
    for (i = 0; i < myPointAnimationUsingKeyFrames.KeyFrames.Count; i++)
    {
        // Do something with each keyframe; for example,set values.
    }
}

下面的示例与上一个示例类似,即在用户单击屏幕的地方出现椭圆,只是此示例中使用了关键帧。 对关键帧的集合进行迭代并为关键帧动态设置值,以便使椭圆动画出现在合适的位置。

运行此示例

CanvasMouseLeftButtonDown="Handle_MouseDown"Width="600"Height="500"Background="Gray"><Storyboardx:Name="myStoryboard"><PointAnimationUsingKeyFramesx:Name="myPointAnimationUsingKeyFrames"Storyboard.TargetProperty="Center"Storyboard.TargetName="MyAnimatedEllipseGeometry"Duration="0:0:3"><discretePointKeyFrameKeyTime="0:0:0"/><LinearPointKeyFrameKeyTime="0:0:0.5"/><SplinePointKeyFrameKeySpline="0.6,0.00"KeyTime="0:0:2"/></PointAnimationUsingKeyFrames></Canvas>
// Global variables that keep track of the end point// of the last animation.double lastX = 200;
double lastY = 100;
privatevoid Handle_MouseDown(object sender,MouseEventArgs e)
{
    // Retrieve current mouse coordinates.double newX = e.GetPosition(null).X;
    double newY = e.GetPosition(null).Y;

    int i;
    for (i = 0; i < myPointAnimationUsingKeyFrames.KeyFrames.Count; i++)
    {
        PointKeyFrame keyFrame = myPointAnimationUsingKeyFrames.KeyFrames[i];
        if (keyFrame.GetType().Name == "discretePointKeyFrame")
        {
            keyFrame.SetValue(discretePointKeyFrame.ValueProperty,new Point(lastX,lastY));
        }
        elseif (keyFrame.GetType().Name == "LinearPointKeyFrame")
        {

            // The LinearKeyFrame has a value that is part way to the // final end point. In addition,this value has to be on// the correct line; therefore,you need to use the line // formula y = mx + b to find the values of x and y.// Calculate the slope.double m = (newY - lastY) / (newX - lastX);

            // Calculate the y-intercept.double b = newY - (m * newX);

            // Set X to a third of the way to the end point.double intermediateX = lastX + (newX - lastX) / 3;

            // Find the value Y from X and the line formula.double intermediateY = (m * intermediateX) + b;

            // Set the keyframe value to the intermediate x and y value.
            keyFrame.SetValue(LinearPointKeyFrame.ValueProperty,new Point(intermediateX,intermediateY));
        }
        elseif (keyFrame.GetType().Name == "SplinePointKeyFrame")
        {
            keyFrame.SetValue(SplinePointKeyFrame.ValueProperty,new Point(newX,newY));
        }
    }
    myStoryboard.Stop();
    myStoryboard.Begin();
    lastX = newX;
    lastY = newY;
}


注意

说明:

Storyboard 具有 Children 属性,该属性允许您访问指定 Storyboard 中的所有动画对象。

动态更改 Storyboard.TargetName 属性最常见的情况是您想将同一动画应用到多个对象。 当具有要应用相似动画的大量对象时,这特别有用。 例如,您可能要显示几行图像并使用动画突出显示鼠标当前所指示的图像。 为每个图像创建单独的 Storyboard 对象非常麻烦。 重用同一 Storyboard 更为合适。

下面的示例涉及很多矩形,当您单击这些矩形时,它们会逐渐消失,接着重新显示 所有这些矩形使用同一 Storyboard,因为呈现 Opacity 动画效果DoubleAnimation 将 TargetName 更改为所单击的矩形。

运行此示例

StackPanelOrientation="Horizontal"><StackPanel.Resources><DoubleAnimationx:Name="myDoubleAnimation"Storyboard.TargetProperty="Opacity"From="1.0"To="0.0"Duration="0:0:2"AutoReverse="True"/></Rectanglex:Name="MyAnimatedRectangle1"Margin="3"Width="100"Height="100"Fill="Blue"MouseLeftButtonDown="Start_Animation"/><Rectanglex:Name="MyAnimatedRectangle2"Margin="3"Width="100"Height="100"Fill="Blue"MouseLeftButtonDown="Start_Animation"/><Rectanglex:Name="MyAnimatedRectangle3"Margin="3"Width="100"Height="100"Fill="Blue"MouseLeftButtonDown="Start_Animation"/><Rectanglex:Name="MyAnimatedRectangle4"Margin="3"Width="100"Height="100"Fill="Blue"MouseLeftButtonDown="Start_Animation"/></StackPanel>
privatevoid Start_Animation(object sender,MouseEventArgs e)
{

    // If the Storyboard is running and you try to change// properties of its animation objects programmatically,// an error will occur.
    myStoryboard.Stop();

    // Get a reference to the rectangle that was clicked.
    Rectangle myRect = (Rectangle)sender;

    // Change the TargetName of the animation to the name of the// rectangle that was clicked.
    myDoubleAnimation.SetValue(Storyboard.TargetNameProperty,myRect.Name);

    // Begin the animation.
    myStoryboard.Begin();
}


在前面的代码中,请注意您在动态更改动画对象的属性前必须停止 Storyboard,否则将出错。 在此示例中,可能不希望只有停止一个矩形的动画才能启动另一个矩形的动画。 可能您想同时运行这两个动画。 但是,您不能使用同一个动画对象同时运行两个独立的动画,因为只有一个 TargetName 这并不意味着您不得不重新为每个对象创建单独的 Storyboard 您只需要为并发(同步)运行的每个动画提供一个 Storyboard 下面的示例与上一个示例类似,只是它包含三个而不是一个Storyboard 对象。 您单击矩形时,事件处理程序查找当前未使用的 Storyboard 并使用它来创建动画。

运行此示例

Storyboardx:Name="myStoryboard1"Completed="Storyboard_Completed"><DoubleAnimationx:Name="myDoubleAnimation1"Storyboard.TargetProperty="Opacity"From="1.0"To="0.0"Duration="0:0:2"AutoReverse="True"/></Storyboard><Storyboardx:Name="myStoryboard2"Completed="Storyboard_Completed"><DoubleAnimationx:Name="myDoubleAnimation2"Storyboard.TargetProperty="Opacity"From="1.0"To="0.0"Duration="0:0:2"AutoReverse="True"/></Storyboardx:Name="myStoryboard3"Completed="Storyboard_Completed"><DoubleAnimationx:Name="myDoubleAnimation3"Storyboard.TargetProperty="Opacity"From="1.0"To="0.0"Duration="0:0:2"AutoReverse="True"/></StackPanel>
bool storyboard1Active = false;
bool storyboard2Active = false;
bool storyboard3Active = false;

privatevoid Start_Animation(object sender,MouseEventArgs e)
{
    // Get a reference to the rectangle that was clicked.
    Rectangle myRect = (Rectangle)sender;
    if (!storyboard1Active)
    {
        myStoryboard1.Stop();
        myDoubleAnimation1.SetValue(Storyboard.TargetNameProperty,myRect.Name);
        myStoryboard1.Begin();
        storyboard1Active = true;
    }
    elseif (!storyboard2Active)
    {
        myStoryboard2.Stop();
        myDoubleAnimation2.SetValue(Storyboard.TargetNameProperty,myRect.Name);
        myStoryboard2.Begin();
        storyboard2Active = true;
    }
    elseif (!storyboard3Active)
    {
        myStoryboard3.Stop();
        myDoubleAnimation3.SetValue(Storyboard.TargetNameProperty,myRect.Name);
        myStoryboard3.Begin();
        storyboard3Active = true;
    }
}

privatevoid Storyboard_Completed(object sender,EventArgs e)
{
    Storyboard myStoryboard = sender as Storyboard;
    switch (myStoryboard.GetValue(NameProperty).ToString())
    {
        case"myStoryboard1": storyboard1Active = false; break;

        case"myStoryboard2": storyboard2Active = false; break;

        case"myStoryboard3": storyboard3Active = false; break;
    }
}


在上面的示例中,同时只能运行三个动画(等于 Storyboard 对象的数目)。 如果您不需要同时运行更多动画,这个示例就可以满足要求了,否则将需要更多的Storyboard 对象。 如果要同时运行很多独立的动画,可能要动态创建 Storyboard 对象。 有关在代码中创建演示图板对象的示例,请参见下一节。

您还可以完全在程序代码中创建动画。 下面的示例演示如何创建一个动画,在其中用动画呈现矩形的 Canvas.Top 和 Canvas.Left 附加属性

运行此示例

private void Create_And_Run_Animation(object sender,EventArgs e)
{
    // Create a red rectangle that will be the target
    // of the animation.
    Rectangle myRectangle = new Rectangle();
    myRectangle.Width = 200;
    myRectangle.Height = 200;
    Color myColor = Color.FromArgb(255,255,0);
    SolidColorBrush myBrush = new SolidColorBrush();
    myBrush.Color = myColor;
    myRectangle.Fill = myBrush;

    // Add the rectangle to the tree.
    LayoutRoot.Children.Add(myRectangle);

    // Create a duration of 2 seconds.
    Duration duration = new Duration(TimeSpan.FromSeconds(2));

    // 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,myRectangle);
    Storyboard.SetTarget(myDoubleAnimation2,myRectangle);

    // 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,21)">"(Canvas.Top)"));

    myDoubleAnimation1.To = 200;
    myDoubleAnimation2.To = 200;

    // Make the Storyboard a resource.
    LayoutRoot.Resources.Add("unique_id",sb);

    // Begin the animation.
    sb.Begin();
}


注意

 说明:

不要试图在页面的构造函数调用 Storyboard 成员(例如 Begin 方法)。 这将导致动画失败,且无任何提示

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐