silverlight做一些复杂动画时,不可能所有的动画都事先用Blend之类的设计工具"画"好(或者在设计期就在vs里编好),很多时候我们希望在运行时能动态控制动画,或者凭空动态创建一段动画.
sl3.0的官方sdk文档里有一节"以编程方式使用动画"讲的就是这个,今天研究了下整理分析于此:
对于事先"画"好(或者称之为在设计期准备好的动画),我们可以在运行时通过名字获取动画引用,进而改变某些属性:
1.示例1(代码来自sdk,以下同),运行时动态改变动画的To属性值,从而实现鼠标点击跟随效果
Xaml部分:
1. <UserControl x:Class="AnimationControl.Change"
2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4. xmlns:d="http://schemas.microsoft.com/Expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5. mc:Ignorable="d" >
6. <Canvas MouseleftbuttonDown="Handle_MouseDown"Background="DarkSeaGreen" WIDth="400"Height="300" Cursor="Hand">
7. <Canvas.Resources>
8. <Storyboardx:name="myStoryboard">
9. <PointAnimation x:name="myPointAnimation"Storyboard.TargetProperty="Center"Storyboard.Targetname="MyAnimatedEllipseGeometry"Duration="0:0:0.5"/>
10. </Storyboard>
11. </Canvas.Resources>
12.
13. <TextBlock Text="请在圆形之外的空白处点击" Foreground="White"@R_403_6837@Stretch="normal" @R_403_6837@Weight="Bold"@R_403_6837@Size="18" TextAlignment="Center"Canvas.left="100" Canvas.top="130" Cursor="Hand"Opacity="0.5">
14.
15. </TextBlock>
16.
17. <Path Fill="Blue">
18. <Path.Data>
19. <EllipseGeometry x:name="MyAnimatedEllipseGeometry"Center="200,100" RadiusX="15" RadiusY="15" />
20. </Path.Data>
21. </Path>
22.
23.
24. </Canvas>
25.</UserControl>
复制代码
布局很简单,一个Canvas上放了一个圆,并创建了一个动画myPointAnimation
CS部分:
1. using System.windows;
2. using System.windows.Controls;
3. using System.windows.input;
4.
5. namespace AnimationControl
6. {
7. public partial class Change : UserControl
8. {
9. public Change()
10. {
11. InitializeComponent();
12. }
13.
14. private voID Handle_MouseDown(objectsender,MousebuttonEventArgs e)
15. {
16. //取得鼠标当前在Canvas中的点击坐标
17. double newX =e.Getposition(sender as UIElement).X;
18. double newY = e.Getposition(senderas UIElement).Y;
19. Point myPoint = newPoint();
20. myPoint.X = newX;
21. myPoint.Y = newY;
22.
23. //动态设置动画的To属性值
24. myPointAnimation.To =myPoint;
25.
26. //播放
27. myStoryboard.Begin();
28. }
29.
30. }
31.}
复制代码
代码不长,一看就明,获取鼠标的点击坐标后,赋值为动画myPointAnimation的To属性(即移动后的目标坐标值),然后播放
2.示例2,有时候很多对象可能会引用到同一效果的动画,每个对象都去创建一个动画太浪费,这时候我们可以把类似的动画通过改变Tartgetname值得以重用
但有一点要注意:因为同一个动画同一时间只能有一个Target,所以如果给这个动画赋值了Tartgetname,并且该动画正在播放的过程中,又用代码给动画的Targetname属性赋值另外一个对象,并要求播放,显示是会失效的。(实际测试中发现,虽然这样不会抛出任何异常)
为避免这种错误的发生,sdk中的示例代码提示我们可以这样做:
Xaml部分:
1. <UserControl x:Class="AnimationControl.Change2"
2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4. xmlns:d="http://schemas.microsoft.com/Expression/blend/2008"
5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6. mc:Ignorable="d"
7. >
8.
9. <StackPanel OrIEntation="Horizontal">
10. <StackPanel.Resources>
11. <Storyboardx:name="myStoryboard1" Completed="Storyboard_Completed">
12. <DoubleAnimation x:name="myDoubleAnimation1"Storyboard.TargetProperty="Opacity" From="1.0"To="0.0" Duration="0:0:2" autoReverse="True"/>
13. </Storyboard>
14. <Storyboardx:name="myStoryboard2" Completed="Storyboard_Completed">
15. <DoubleAnimation x:name="myDoubleAnimation2"Storyboard.TargetProperty="Opacity" From="1.0"To="0.0" Duration="0:0:2" autoReverse="True"/>
16. </Storyboard>
17. <Storyboardx:name="myStoryboard3" Completed="Storyboard_Completed">
18. <DoubleAnimation x:name="myDoubleAnimation3" Storyboard.TargetProperty="Opacity"From="1.0" To="0.0" Duration="0:0:2"autoReverse="True" />
19. </Storyboard>
20. </StackPanel.Resources>
21. <Rectanglex:name="MyAnimatedRectangle1" margin="3"WIDth="90" Height="100" Fill="Blue"MouseleftbuttonDown="Start_Animation" Cursor="Hand" />
22. <Rectanglex:name="MyAnimatedRectangle2" margin="3"WIDth="90" Height="100" Fill="Blue"MouseleftbuttonDown="Start_Animation" Cursor="Hand" />
23. <Rectanglex:name="MyAnimatedRectangle3" margin="3"WIDth="90" Height="100" Fill="Blue"MouseleftbuttonDown="Start_Animation" Cursor="Hand" />
24. <Rectanglex:name="MyAnimatedRectangle4" margin="3"WIDth="90" Height="100" Fill="Blue"MouseleftbuttonDown="Start_Animation" Cursor="Hand" />
25. </StackPanel>
26.
27.</UserControl>
复制代码
StackPanel中横向放了4个矩形,同时放置了三个完全相同的double型动画(用来让对象的透明度从1变到0,即渐渐淡去),实现目的:4个矩形,3个动画,显示按照一一对应的默认原则,总会有一个矩形无法分配到动画,如何实现重用呢?看下面的
cs部分:
1. using System;
2. using System.windows.Controls;
3. using System.windows.input;
4. using System.windows.Media.Animation;
5. using System.windows.Shapes;
6.
7. namespace AnimationControl
8. {
9. public partial class Change2 : UserControl
10. {
11. public Change2()
12. {
13. InitializeComponent();
14. }
15.
16. bool storyboard1Active = false;
17. bool storyboard2Active = false;
18. bool storyboard3Active = false;
19.
20. private voID Start_Animation(objectsender,MouseEventArgs e)
21. {
22. //得到被点击的矩形对象引用
23. Rectangle myRect =(Rectangle)sender;
24.
25. if (!storyboard1Active)
26. {
27. myStoryboard1.Stop();
28. myDoubleAnimation1.SetValue(Storyboard.TargetnameProperty,myRect.name);
29. myStoryboard1.Begin();
30. storyboard1Active = true;
31. }
32. else if(!storyboard2Active)
33. {
34. myStoryboard2.Stop();
35. myDoubleAnimation2.SetValue(Storyboard.TargetnameProperty,myRect.name);
36. myStoryboard2.Begin();
37. storyboard2Active = true;
38. }
39. else if(!storyboard3Active)
40. {
41. myStoryboard3.Stop();
42. myDoubleAnimation3.SetValue(Storyboard.TargetnameProperty,myRect.name);
43. myStoryboard3.Begin();
44. storyboard3Active = true;
45. }
46. }
47.
48. private voIDStoryboard_Completed(object sender,EventArgs e)
49. {
50. StoryboardmyStoryboard = sender as Storyboard;
51. switch(myStoryboard.GetValue(nameProperty).ToString())
52. {
53. case"myStoryboard1": storyboard1Active = false; break;
54. case"myStoryboard2": storyboard2Active = false; break;
55. case"myStoryboard3": storyboard3Active = false; break;
56. }
57. }
58.
59. }
60.}
复制代码
这里注意:定义了三个标识变量,用于标识每个动画是否正在播放中,如果播放完成后该变量为false,否则为true(即正在播放),这个每个矩形上点击请求播放动画时,总是优先找到空闲(即不处于播放状态)的动画,然后为该动画赋值Targetname属性并播放,同时播放途中把对应的标识变量改成true,以防止播放过程中被人修改Targetname值
也许有人会问了:如果没找到空闲的动画,不是没效果了?Yes,你猜对了,如果快速依次点击4个矩形,会发现最后一次点击没什么变化。这种情况就要用到下面提到的代码动态创建动画了
3。示例3 代码动态创建动画
理解起来很简单,代码创建动画对象,并让其播放。
xaml部分:
1. <UserControl x:Class="AnimationControl.Create"
2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4. xmlns:d="http://schemas.microsoft.com/Expression/blend/2008"
5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6. mc:Ignorable="d"
7. >
8.
9. <Canvas name="LayoutRoot"Background="DarkOliveGreen" WIDth="400"Height="300">
10. <TextBlock Text="点击我将动态创建一段动画" MouseleftbuttonDown="TextBlock_MouseleftbuttonDown"Foreground="White" @R_403_6837@Stretch="normal"@R_403_6837@Weight="Bold" @R_403_6837@Size="18"TextAlignment="Center" Canvas.left="100" Canvas.top="130"Cursor="Hand" Opacity="0.5">
11.
12. </TextBlock>
13. </Canvas>
14.</UserControl>
复制代码
一个几乎是空的Canvas,没啥特别的
再来看cs部分:
1. using System;
2. using System.windows;
3. using System.windows.Controls;
4. using System.windows.Media;
5. using System.windows.Media.Animation;
6. using System.windows.Shapes;
7.
8. namespace AnimationControl
9. {
10. public partial class Create : UserControl
11. {
12. public Create()
13. {
14.
15. InitializeComponent();
16.
17. }
18.
19. public voID CreateAnimation()
20. {
21. //创建一个矩形
22. Rectangle myRectangle= new Rectangle();
23. myRectangle.WIDth =50;
24. myRectangle.Height =50;
25. myRectangle.Fill = newSolIDcolorBrush(color.FromArgb(255,255,0));
26.
27. //把矩形加入到Canvas中
28. LayoutRoot.Children.Add(myRectangle);
29.
30. //创建二个double型的动画,并设定播放时间为2秒
31. Duration duration =new Duration(TimeSpan.FromSeconds(2));
32. DoubleAnimationmyDoubleAnimation1 = new DoubleAnimation();
33. DoubleAnimationmyDoubleAnimation2 = new DoubleAnimation();
34.
35. myDoubleAnimation1.Duration = duration;
36. myDoubleAnimation2.Duration = duration;
37.
38. //创建故事版,并加入上面的二个double型动画
39. Storyboard sb = newStoryboard();
40. sb.Duration =duration;
41.
42. sb.Children.Add(myDoubleAnimation1);
43. sb.Children.Add(myDoubleAnimation2);
44.
45. //设置动画的Target目标值
46. Storyboard.SetTarget(myDoubleAnimation1,myRectangle);
47. Storyboard.SetTarget(myDoubleAnimation2,myRectangle);
48.
49. //设置动画的变化属性
50. Storyboard.SetTargetProperty(myDoubleAnimation1,newPropertyPath("(Canvas.left)"));
51. Storyboard.SetTargetProperty(myDoubleAnimation2,newPropertyPath("(Canvas.top)"));
52.
53. myDoubleAnimation1.To= 200;
54. myDoubleAnimation2.To= 200;
55.
56. if(!LayoutRoot.Resources.Contains("unique_ID"))
57. {
58. //将动画版加入Canvas资源,注意:这里的unique_ID必须是资源中没有的唯一键
59. LayoutRoot.Resources.Add("unique_ID",sb);
60. sb.Completed += new EventHandler(sb_Completed);
61.
62. //播放
63. sb.Begin();
64. }
65. else
66. {
67. sb =null;
68. LayoutRoot.Children.Remove(myRectangle);
69. }
70.
71.
72.
73. }
74.
75. voID sb_Completed(object sender,EventArgs e)
76. {
77. LayoutRoot.Resources.Remove("unique_ID");//播放完成后,移除资源,否则再次点击时将报错
78. }
79.
80. private voID TextBlock_MouseleftbuttonDown(objectsender,System.windows.input.MousebuttonEventArgs e)
81. {
82. CreateAnimation();
83. }
84. }
85.}
复制代码
几乎所有关键的地方,都加了注释了应该能容易看明白
这里有一点要注意:创建动画的代码,必须放在构造函数中的InitializeComponent()之后调用,原因很简单,如果组件尚未初始化完毕,这时向根容器加入一些动态创建的元件当然会报错。
以上是内存溢出为你收集整理的silverlight如何在运行时用代码动态控制(或创建)动画全部内容,希望文章能够帮你解决silverlight如何在运行时用代码动态控制(或创建)动画所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)