我是靠谱客的博主 文艺鲜花,这篇文章主要介绍WPF动画详解一、概述二、简单独立动画三、场景,现在分享给大家,希望可以做个参考。

目录

一、概述

二、简单独立动画

2.1 简单线性动画

2.2 高级动画控制

2.3 关键帧动画

2.4 特殊的关键帧

2.5 路径动画

三、场景


一、概述

动画的本质就是在一个时间段内对象位置、角度、颜色、透明度等属性值的连续变化。这些属性种,有些是对象自身的单属性,有些是图形变形 的属性。WPF规定,可以用来制作动画的属性必须是依赖属性。

简单的动画由一个元素来完成就可以了,就像一个演员的独角戏,WPF吧简单动画称为AnimationTimeline。复杂的动画就需要UI上的多个元素协同完成,就像电影中的一段场景。复杂动画的协同包括有哪些UI元素参与动画、每个元素的动画行为是什么、动画何时开始何时结束等。WPF把一组协同的动画也称为Storyboard。

二、简单独立动画

动画就是“会动的画”,而这个会动值得就是能够让UI元素或元素变形的某个属性值产生连续变化。任何一个属性都有自己的数据类型,比如UIElement的With和Height属性为Double类型、Window的Title属性为String类型。几乎针对每个可能的数据类型,WPF的动画子系统都为其准备了相应的动画类,这些动画类均派生自AnimationTimeline。3种具体动画,即简单动画、关键帧动画、沿路径运动的动画。例如:DoubleAnimationbase,它完整地派生了3个具体动画:DoubleAnimation、DoubleAnimationUsingKeyFrames和DoubleAnimationUsingPath,分别是简单动画、关键帧动画、沿路径运动的动画。

在WPF中,Double类型的属性用的最多,只讲这个类,其他亦可触类旁通。

2.1 简单线性动画

简单线性动画指仅有变化起点、变化终点、变化幅度、变化时间4个要素构成的动画。

变化时间(Duration 属性):必须指定,动画的时长多少

变化终点(To 属性):变化终点,如果没有则采用 上一次动画的终点 或 默认值

变化幅度(By 属性):变化幅度,变化的规律,使用时不可使用变化终点

变化起点(From 属性):变化起点,如果没有指定则以目标属性的当前值为起点。

让我们分析一个简单的实例。例子的XAML代码如下:

复制代码
1
2
3
4
5
6
7
8
9
<Grid> <Button Width="60" Height="60" Content="Move" Click="Button_Click_1" HorizontalAlignment="Left" VerticalAlignment="Top"> <Button.RenderTransform> <TranslateTransform x:Name="tt" X="30" Y="30"/> </Button.RenderTransform> </Button> </Grid> </Window>

 用户界面上只包含一个Button,这个Button的RenderTransform属性值是一个名为tt的TranslateTransform对象,改变这个对象的X和Y值就会让Button的显示位置变化。Button的Click事件处理器代码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private void Button_Click(object sender, RoutedEventArgs e) { DoubleAnimation daX = new DoubleAnimation(); DoubleAnimation daY = new DoubleAnimation(); //指定起点 daX.From = 30; daY.From = 30; //指定终点 Random r = new Random(); daX.To = r.NextDouble() * 300; daY.To = r.NextDouble() * 300; //指定时长 Duration duration = new Duration(TimeSpan.FromMilliseconds(300)); daX.Duration = duration; daY.Duration = duration; //动画的主题是TranslateTransform变形,而非Button this.tt.BeginAnimation(TranslateTransform.XProperty, daX); this.tt.BeginAnimation(TranslateTransform.YProperty, daY); }

因为TranslateTransform的X、Y属性均为Double类型,所以选用DoubleAnimation来产生变化。代码中声明了daX和daY两个DoubleAnimation变量并分别创建引用实例。接下来的代码一次为它们设置了起始值、终止值、变化时间。最后调用DoubleAnimation方法,让daX作用在TranslateTransformXProperty依赖属性上、让daY作用在TranslateTransform的YProperty依赖属性上。

每次单击按钮,按钮都会从起始位置向右下长宽不超过300像素的矩形内的某点运动,完成运动的时长是300毫秒。

效果:

 如果把事件处理器的代码改变成这样:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private void Button_Click(object sender, RoutedEventArgs e) { DoubleAnimation daX = new DoubleAnimation(); DoubleAnimation daY = new DoubleAnimation(); //指定幅度 daX.By= 100D; daY.By = 100D; //指定时长 Duration duration = new Duration(TimeSpan.FromMilliseconds(300)); daX.Duration = duration; daY.Duration = duration; //动画的主题是TranslateTransform变形,而非Button this.tt.BeginAnimation(TranslateTransform.XProperty, daX); this.tt.BeginAnimation(TranslateTransform.YProperty, daY); }

每次单击按钮,按钮都会向窗体的右下角移动。

2.2 高级动画控制

使用From、To、By、Duration几个属性进行组合就可以制作很多不同效果的动画了,然而WPF动画系统提供的控制属性远不止这些。

属性描述     应用举例
AccelerationRatio加速速率( 0.0 - 1.0)与DecelerationRatio之和不大于1.0 模拟汽车启动
DecelerationRatio   减速速率( 0.0 - 1.0)与AccelerationRatio 之和不大于1.0 模拟汽车刹车
SpeedRatio   动画实际播放速度与正常速度的比值 快进播放、慢动作
AutoReverse           是否以相反的动画方式从终点值返回到起始值倒退播放
RepeatBehavior     动画的重复行为,取0为不播放,使用double类性值可控制循环播放次数,取Forever为永远循环循环播放
BeginTime              正式开始播放前的等待时间多个动画之前的协同
EasingFunction       缓冲式渐变乒乓球弹跳效果

在这些属性中,EasingFunction是一个扩展性非常强的属性。它取值是IEasingFunction接口类型,而IEasingFunction派生类就有十几种,每个派生类都能产生不同的结束效果。比如BounceEase可以产生乒乓球弹跳的效果。

如果把前面的例子的代码改成这样:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private void Button_Click(object sender, RoutedEventArgs e) { DoubleAnimation daX = new DoubleAnimation(); DoubleAnimation daY = new DoubleAnimation(); //设置反弹 BounceEase be = new BounceEase(); be.Bounces = 3;//弹跳3次 be.Bounciness = 3;//弹性程度,值越大反弹越低 daY.EasingFunction = be; //指定终点 Random r = new Random(); daX.To = r.NextDouble() * 300; daY.To = r.NextDouble() * 300; //指定时长 Duration duration = new Duration(TimeSpan.FromMilliseconds(2000)); daX.Duration = duration; daY.Duration = duration; //动画的主题是TranslateTransform变形,而非Button this.tt.BeginAnimation(TranslateTransform.XProperty, daX); this.tt.BeginAnimation(TranslateTransform.YProperty, daY); }

产生乒乓球弹跳的效果。

2.3 关键帧动画

动画是UI元素属性连续改变所产生的视觉效果。属性每次细微的变化都会产生一个新的画面,每个新画面就称为一“帧”,帧的连续播放就产生动画的效果。关键帧动画允许程序员为一段动画设置几个里程碑,动画执行到里程碑所在的时间点时,被动画所控制的属性值也必须达到设定的值,这些时间线上的里程碑就是关键帧。

实例:

一个Button在单击后用900毫秒的时长从左上角移动到右下角,但移动路线不是直接移动而是走“Z”字形。

我们只需创建两个DoubleAnimationUsingKeyFrames实例,一个控制TranslateTransform的X属性,一个控制TranslateTransform的Y属性。每个DoubleAnimationUsingKeyFrames各拥有三个关键帧用于指明X或Y在三个时间点(两个拐点和终点)应该达到什么样的值。

程序的XAML代码如下:

复制代码
1
2
3
4
5
6
7
8
<Grid> <Button Width="60" Height="60" Content="Move" Click="Button_Click" HorizontalAlignment="Left" VerticalAlignment="Top"> <Button.RenderTransform> <TranslateTransform x:Name="tt" X="30" Y="30"/> </Button.RenderTransform> </Button> </Grid>

 Button的Click事件处理器代码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
private void Button_Click(object sender, RoutedEventArgs e) { DoubleAnimationUsingKeyFrames dakX = new DoubleAnimationUsingKeyFrames(); DoubleAnimationUsingKeyFrames dakY = new DoubleAnimationUsingKeyFrames(); // 设置动画总时长 dakX.Duration = new Duration(TimeSpan.FromMilliseconds(900)); dakY.Duration = new Duration(TimeSpan.FromMilliseconds(900)); // 创建关键帧 LinearDoubleKeyFrame x_kf_1 = new LinearDoubleKeyFrame(); LinearDoubleKeyFrame x_kf_2 = new LinearDoubleKeyFrame(); LinearDoubleKeyFrame x_kf_3 = new LinearDoubleKeyFrame(); //设置关键帧 x_kf_1.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(300)); x_kf_1.Value = 200; x_kf_2.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(600)); x_kf_2.Value = 0; x_kf_3.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(900)); x_kf_3.Value = 200; //添加关键帧 dakX.KeyFrames.Add(x_kf_1); dakX.KeyFrames.Add(x_kf_2); dakX.KeyFrames.Add(x_kf_3); LinearDoubleKeyFrame y_kf_1 = new LinearDoubleKeyFrame(); LinearDoubleKeyFrame y_kf_2 = new LinearDoubleKeyFrame(); LinearDoubleKeyFrame y_kf_3 = new LinearDoubleKeyFrame(); y_kf_1.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(300)); y_kf_1.Value = 0; y_kf_2.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(600)); y_kf_2.Value = 180; y_kf_3.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(900)); y_kf_3.Value = 180; dakY.KeyFrames.Add(y_kf_1); dakY.KeyFrames.Add(y_kf_2); dakY.KeyFrames.Add(y_kf_3); //执行动画 this.tt.BeginAnimation(TranslateTransform.XProperty, dakX); this.tt.BeginAnimation(TranslateTransform.YProperty, dakY); }

2.4 特殊的关键帧

DoubleAnimationUsingKeyFrames 的KeyFrames 属性的数据类型是DoubleKeyFrameCollection,此集合类可接收的类型为 DoubleKeyFrame。DoubleKeyFrame 是一个抽象类,它的所有派生类如下:

LinearDoubleKeyFrame:线性变化关键帧,目标属性值的变化时是直线性的、均匀的,即变化速率不变。

DiscreteDoubleKeyFrame:不连续变化关键帧,目标属性值的变化是跳跃性的、跃迁的。

SplineDoubleKeyFrame:样条函数式变化关键帧,目标属性的变化速率是一条贝塞尔曲线。

EasingDoubleKeyFrame:缓冲式变化关键帧,目标属性以某种缓冲形式变化。

4个派生类中最常用的是SplineDoubleKeyFrame。可以非常方面的制作非匀速动画,因为他使用一条贝塞尔曲线来控制目标属性值的变化速率。这条用于控制变化速率的贝塞尔曲线的起点是(0,0)和(1,1),分别映射着目标属性的变化起点和变化终点,意思是目标属性值由0%变化到100%。这条曲线的有两个控制点ControlPoint1和ControlPoint2,意思是曲线从起点出发先向ControlPoint1的方向前进、再向ControlPoint2的方向前进、最后到达终点,形成一条平滑的曲线。如果设置ControlPoint1和ControlPoint2的横纵坐标值相等,这是曲线成为一条直线,SplineDoubleKeyFrame和LinearDoubleKeyFrame是等价的。

下面是SplineDoubleKeyFrame的实例

程序的XAML代码如下:

复制代码
1
2
3
4
5
6
7
8
<Grid> <Button Width="60" Height="60" Content="Move" Click="Button_Click" HorizontalAlignment="Left" VerticalAlignment="Top"> <Button.RenderTransform> <TranslateTransform x:Name="tt" X="30" Y="30"/> </Button.RenderTransform> </Button> </Grid>

 Button的Click事件处理器代码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private void Button_Click(object sender, RoutedEventArgs e) { // 创建动画 DoubleAnimationUsingKeyFrames dakX = new DoubleAnimationUsingKeyFrames(); dakX.Duration = new Duration(TimeSpan.FromMilliseconds(1000)); //创建、添加关键帧 SplineDoubleKeyFrame kf = new SplineDoubleKeyFrame(); kf.KeyTime = KeyTime.FromPercent(1); kf.Value = 400; //设置速率 KeySpline ks = new KeySpline(); ks.ControlPoint1 = new Point(0, 1); ks.ControlPoint2 = new Point(1, 0); kf.KeySpline = ks; dakX.KeyFrames.Add(kf); //执行动画 this.tt.BeginAnimation(TranslateTransform.XProperty, dakX); }

 关键帧动画会控制Button的位置变形、让Button横向移动。整个动画只有一个关键帧,这个关键帧使用的是SplineDoubleKeyFrame变化速率控制曲线的两个控制点分别是(0,1)(1,0),目标属性会以“快-慢-快”的形式变化。

2.5 路径动画

如何让目标对象沿着一条给定的路径移动呢?答案是使用DoubleAnimationUsingPath类。DoubleAnimationUsingPath需要一个PathGeometry来指明移动路径,PathGeometry的数据信息可以用XAML的Path语法书写。PathGeometry的另一个重要属性是Source,Source属性的数据类型是PathAnimationSource枚举,枚举值可取X(关注曲线上每一点横坐标的变化)、Y(关注曲线上每一点纵坐标的变化)或Angle关注曲线上每一点处切线方向的变化。

实例:

让Button沿着一条贝塞尔曲线做波浪形运动。程序XAML代码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<Grid> <Grid x:Name="LayoutRoot"> <!--移动路径--> <Grid.Resources> <PathGeometry x:Key="movingPath" Figures="M 0,150 C 300,-100 300,400 600,120"/> </Grid.Resources> <Button Content="Move" HorizontalAlignment="Left" VerticalAlignment="Top" Width="80" Height="80" Click="Button_Click"> <Button.RenderTransform> <TranslateTransform x:Name="tt" X="0" Y="0"/> </Button.RenderTransform> </Button> </Grid> </Grid>

Button的Click事件处理器代码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
private void Button_Click(object sender, RoutedEventArgs e) { // 查找资源 PathGeometry pg = this.LayoutRoot.FindResource("movingPath") as PathGeometry; Duration duration = new Duration(TimeSpan.FromMilliseconds(600));// 设置动画时间 // 创建动画 DoubleAnimationUsingPath dapX = new DoubleAnimationUsingPath(); dapX.PathGeometry = pg; dapX.Source = PathAnimationSource.X; dapX.Duration = duration; DoubleAnimationUsingPath dapY = new DoubleAnimationUsingPath(); dapY.PathGeometry = pg; dapY.Source = PathAnimationSource.Y; dapY.Duration = duration; //设置来回循环效果 dapX.AutoReverse = true; dapX.RepeatBehavior = RepeatBehavior.Forever; dapY.AutoReverse = true; dapY.RepeatBehavior = RepeatBehavior.Forever; //执行动画 this.tt.BeginAnimation(TranslateTransform.XProperty, dapX); this.tt.BeginAnimation(TranslateTransform.YProperty, dapY); }

三、场景

场景就是并行执行的一组动画。

先是把一组独立的动画组织在一个Storyboard元素中、安排好他们的协作关系,然后制定哪个动画由哪个UI元素、哪个属性负责完成。Storyboard设计好后,你可以为他选择一个恰当的触发时机,比如按钮按下或下载开始时。一旦触发条件被满足,动画产经就会开始执行。

实例:

程序XAML代码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<Grid Margin="6"> <!--布局控制--> <Grid.RowDefinitions> <RowDefinition Height="38"/> <RowDefinition Height="38"/> <RowDefinition Height="38"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="60"/> </Grid.ColumnDefinitions> <!--跑道红--> <Border BorderBrush="Gray" BorderThickness="1" Grid.Row="0"> <Ellipse x:Name="ballR" Height="36" Width="36" Fill="Red" HorizontalAlignment="Left"> <Ellipse.RenderTransform> <TranslateTransform x:Name="ttR"/> </Ellipse.RenderTransform> </Ellipse> </Border> <!--跑道绿--> <Border BorderBrush="Gray" BorderThickness="1,0,1,1" Grid.Row="1"> <Ellipse x:Name="ballG" Height="36" Width="36" Fill="LawnGreen" HorizontalAlignment="Left"> <Ellipse.RenderTransform> <TranslateTransform x:Name="ttG"/> </Ellipse.RenderTransform> </Ellipse> </Border> <!--跑道蓝--> <Border BorderBrush="Gray" BorderThickness="1,0,1,1" Grid.Row="2"> <Ellipse x:Name="ballB" Height="36" Width="36" Fill="Blue" HorizontalAlignment="Left"> <Ellipse.RenderTransform> <TranslateTransform x:Name="ttB"/> </Ellipse.RenderTransform> </Ellipse> </Border> <!--按钮--> <Button Content="Go!" Grid.Column="1" Grid.RowSpan="3"> <!--按钮触发--> <Button.Triggers> <EventTrigger RoutedEvent="Button.Click"> <BeginStoryboard> <Storyboard Duration="0:0:0.6"> <!--红色小球动画--> <DoubleAnimation Duration="0:0:0.6" To="400" Storyboard.TargetName="ttR" Storyboard.TargetProperty="X"/> <!--绿色小球动画--> <DoubleAnimationUsingKeyFrames Duration="0:0:0.6" Storyboard.TargetName="ttG" Storyboard.TargetProperty="X"> <SplineDoubleKeyFrame KeyTime="0:0:0.6" Value="400" KeySpline="0,1,1,0"/> </DoubleAnimationUsingKeyFrames> <!--蓝色小球动画--> <DoubleAnimationUsingKeyFrames Duration="0:0:0.6" Storyboard.TargetName="ttB" Storyboard.TargetProperty="X"> <SplineDoubleKeyFrame KeyTime="0:0:0.6" Value="400" KeySpline="1,0,0,1"/> </DoubleAnimationUsingKeyFrames> </Storyboard> </BeginStoryboard> </EventTrigger> </Button.Triggers> </Button> </Grid>

 效果:

最后

以上就是文艺鲜花最近收集整理的关于WPF动画详解一、概述二、简单独立动画三、场景的全部内容,更多相关WPF动画详解一、概述二、简单独立动画三、场景内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部