有时您可能要动态(即时)更改动画的属性,
Silverlight:以编程方式使用动画
。例如,您可能要调整应用到对象 的动画行为,这取决于对象当前在布局中的位置、对象包含何种内容等等。可以 通过使用程序代码(例如 C# 或 Visual Basic)动态操作动画。先决条件
您应熟悉 Silverlight 动画。有关简介,请参见动画概述。
通过名称访问动画
访问动画对象以更改其属性的最直接方法是:命名该动画对象,然后在代码中 通过该名称引用它。下面的示例包含一个 Ellipse,当您在屏幕上单击时它将显 示动画效果。为了实现此动画,在单击 Canvas 时,事件处理程序更改 PointAnimation 对象的 To 属性,然后启动动画。
运行此示例:http://go.microsoft.com/fwlink/? LinkId=139798&sref=change_animation_properties_1
XAML
Background="Gray" Width="600" Height="500">
Storyboard.TargetProperty="Center"
Storyboard.TargetName="MyAnimatedEllipseGeometry"
Duration="0:0:2"/>
VB
Private Sub Handle_MouseDown(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
' Retrieve current mouse coordinates.
Dim newX As Double = e.GetPosition(Nothing).X
Dim newY As Double = e.GetPosition(Nothing).Y
Dim myPoint As Point = New Point
myPoint.X = newX
myPoint.Y = newY
myPointAnimation.To = myPoint
myStoryboard.Begin()
End Sub
C#
private void Handle_MouseDown(object sender, MouseButtonEventArgs
e)<br />{<br /> // Retrieve current mouse coordinates.<br /> double
newX = e.GetPosition(null).X;<br /> double newY = e.GetPosition
(null).Y;<br /> Point myPoint = new Point();<br /> myPoint.X =
newX;<br /> myPoint.Y = newY;<br /> myPointAnimation.To =
myPoint;<br /> myStoryboard.Begin();<br />}
使所有动画具有唯一的名称有时不易做到。这时您可以使用集合来访问动画或 动画的关键帧。例如,如果要以编程方式访问 DoubleAnimationUsingKeyFrames 对象中的所有关键帧,可以使用与以下代码类似的代码:
XAML
Width="600" Height="500" Background="Gray">
Storyboard.TargetProperty="Center"
Storyboard.TargetName="MyAnimatedEllipseGeometry"
Duration="0:0:3">
C#
public void Handle_MouseDown(object sender, MouseEventArgs e)<br />
{<br /> int i;<br /> for (i = 0; i <
myPointAnimationUsingKeyFrames.KeyFrames.Count; i++)<br /> {<br />
// Do something with each keyframe; for example, set values.<br /> }
<br />}
下面的示例与上一个示例类似,即在用户单击屏幕的地方出现椭圆,只是此示 例中使用了关键帧。对关键帧的集合进行迭代并为关键帧动态设置值,以便使椭 圆动画出现在合适的位置。
运行此示例:http://go.microsoft.com/fwlink/? LinkId=139798&sref=access_keyframe_collection
XAML
Width="600" Height="500" Background="Gray">
Storyboard.TargetProperty="Center"
Storyboard.TargetName="MyAnimatedEllipseGeometry"
Duration="0:0:3">
C#
' Global variables that keep track of the end point
' of the last animation.
Private lastX As Double = 200
Private lastY As Double = 100
Private Sub Handle_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs)
' Retrieve current mouse coordinates.
Dim newX As Double = e.GetPosition(Nothing).X
Dim newY As Double = e.GetPosition(Nothing).Y
Dim i As Integer
i = 0
Do While (i < myPointAnimationUsingKeyFrames.KeyFrames.Count)
Dim keyFrame. As PointKeyFrame. = myPointAnimationUsingKeyFrames.KeyFrames(i)
If (keyFrame.GetType.Name = "DiscretePointKeyFrame") Then
keyFrame.SetValue (DiscretePointKeyFrame.ValueProperty, New Point(lastX, lastY))
ElseIf (keyFrame.GetType.Name = "LinearPointKeyFrame") Then
' 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
Dim m As Double = ((newY - lastY) / (newX - lastX))
' Calculate the y-intercept.
Dim b As Double = (newY - (m * newX))
' Set X to a third of the way to the end point.
Dim intermediateX As Double = (lastX + ((newX - lastX) / 3))
' Find the value Y from X and the line formula.
Dim intermediateY As Double = ((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") Then
keyFrame.SetValue (SplinePointKeyFrame.ValueProperty, New Point(newX, newY))
End If
i = (i + 1)
Loop
myStoryboard.Stop()
myStoryboard.Begin()
lastX = newX
lastY = newY
End Sub
注意说明:
Storyboard 具有 Children 属性,该属性允许您访问指定 Storyboard 中的 所有动画对象。
动态更改 TargetName
动态更改 Storyboard.TargetName 属性最常见的情况是您想将同一动画应用 到多个对象。当具有要应用相似动画的大量对象时,这特别有用。例如,您可能 要显示几行图像并使用动画突出显示鼠标当前所指示的图像。为每个图像创建单 独的 Storyboard 对象非常麻烦。重用同一 Storyboard 更为合适。
下面的示例涉及很多矩形,当您单击这些矩形时,它们会逐渐消失,接着重新 显示。所有这些矩形使用同一 Storyboard,因为呈现 Opacity 动画效果的 DoubleAnimation 将 TargetName 更改为所单击的矩形。
运行此示例:http://go.microsoft.com/fwlink/? LinkId=139798&sref=change_targetname_1
XAML
From="1.0" To="0.0" Duration="0:0:2"
AutoReverse="True" />
Margin="3" Width="100" Height="100" Fill="Blue"
MouseLeftButtonDown="Start_Animation" />
Margin="3" Width="100" Height="100" Fill="Blue"
MouseLeftButtonDown="Start_Animation" />
Margin="3" Width="100" Height="100" Fill="Blue"
MouseLeftButtonDown="Start_Animation" />
Margin="3" Width="100" Height="100" Fill="Blue"
MouseLeftButtonDown="Start_Animation" />
VB
Private Sub Start_Animation(ByVal sender As Object, ByVal e As MouseEventArgs)
' 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.
Dim myRect As Rectangle = CType(sender, Rectangle)
' 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()
End Sub
在前面的代码中,请注意您在动态更改动画对象的属性前必须停止 Storyboard,否则将出错,
电脑资料
《Silverlight:以编程方式使用动画》(https://www.unjs.com)。在此示例中,可能不希望只有停止一个矩形的动画才 能启动另一个矩形的动画。可能您想同时运行这两个动画。但是,您不能使用同 一个动画对象同时运行两个独立的动画,因为只有一个 TargetName。这并不意味 着您不得不重新为每个对象创建单独的 Storyboard。您只需要为并发(同步)运 行的每个动画提供一个 Storyboard。下面的示例与上一个示例类似,只是它包含 三个而不是一个 Storyboard 对象。您单击矩形时,事件处理程序查找当前未使 用的 Storyboard 并使用它来创建动画。运行此示例:http://go.microsoft.com/fwlink/? LinkId=139798&sref=change_targetname_2
XAML
From="1.0" To="0.0" Duration="0:0:2" AutoReverse="True" />
From="1.0" To="0.0" Duration="0:0:2"
AutoReverse="True" />
From="1.0" To="0.0" Duration="0:0:2"
AutoReverse="True" />
MouseLeftButtonDown="Start_Animation" />
MouseLeftButtonDown="Start_Animation" />
MouseLeftButtonDown="Start_Animation" />
MouseLeftButtonDown="Start_Animation" />
VB
Private storyboard1Active As Boolean = False
Private storyboard2Active As Boolean = False
Private storyboard3Active As Boolean = False
Private Sub Start_Animation(ByVal sender As Object, ByVal e As MouseEventArgs)
' Get a reference to the rectangle that was clicked.
Dim myRect As Rectangle = CType(sender, Rectangle)
If Not storyboard1Active Then
myStoryboard1.Stop()
myDoubleAnimation1.SetValue (Storyboard.TargetNameProperty, myRect.Name)
myStoryboard1.Begin()
storyboard1Active = True
ElseIf Not storyboard2Active Then
myStoryboard2.Stop()
myDoubleAnimation2.SetValue (Storyboard.TargetNameProperty, myRect.Name)
myStoryboard2.Begin()
storyboard2Active = True
ElseIf Not storyboard3Active Then
myStoryboard3.Stop()
myDoubleAnimation3.SetValue (Storyboard.TargetNameProperty, myRect.Name)
myStoryboard3.Begin()
storyboard3Active = True
End If
End Sub
Private Sub Storyboard_Completed(ByVal sender As Object, ByVal e As EventArgs)
Dim myStoryboard As Storyboard = CType(sender, Storyboard)
Select Case (myStoryboard.GetValue (NameProperty).ToString)
Case "myStoryboard1"
storyboard1Active = False
Case "myStoryboard2"
storyboard2Active = False
Case "myStoryboard3"
storyboard3Active = False
End Select
End Sub
在上面的示例中,同时只能运行三个动画(等于 Storyboard 对象的数目)。 如果您不需要同时运行更多动画,这个示例就可以满足要求了,否则将需要更多 的 Storyboard 对象。如果要同时运行很多独立的动画,可能要动态创建 Storyboard 对象。有关在代码中创建演示图板对象的示例,请参见下一节。
在程序代码中创建动画
您还可以完全在程序代码中创建动画。下面的示例演示如何创建一个动画,在 其中用动画呈现矩形的 Canvas.Top 和 Canvas.Left 附加属性。
运行此示例:http://go.microsoft.com/fwlink/? LinkId=139798&sref=programmatic_animation
VB
Private Sub Create_And_Run_Animation(ByVal sender As Object, ByVal e As EventArgs)
' Create a red rectangle that will be the target
' of the animation.
Dim myRectangle As Rectangle = New Rectangle
myRectangle.Width = 200
myRectangle.Height = 200
Dim myColor As Color = Color.FromArgb(255, 255, 0, 0)
Dim myBrush As SolidColorBrush = New SolidColorBrush
myBrush.Color = myColor
myRectangle.Fill = myBrush
' Add the rectangle to the tree.
LayoutRoot.Children.Add(myRectangle)
' Create a duration of 2 seconds.
Dim duration As Duration = New Duration (TimeSpan.FromSeconds(2))
' Create two DoubleAnimations and set their properties.
Dim myDoubleAnimation1 As DoubleAnimation = New DoubleAnimation
Dim myDoubleAnimation2 As DoubleAnimation = New DoubleAnimation
myDoubleAnimation1.Duration = duration
myDoubleAnimation2.Duration = duration
Dim sb As Storyboard = 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, 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()
End Sub
注意说明:
不要试图在页面的构造函数中调用 Storyboard 成员(例如 Begin 方法)。 这将导致动画失败,且无任何提示。