不可不知的WPF动画(Animation) (Animation) Animation 不可不知的 WPF 动画
在WPF开发应用中,动画不仅可以引起用户的注意与兴趣,而且还使软件更加便于使用。前面几篇文章讲解了画笔(Brush),形状(Shape),几何图形(Geometry),变换(Transform)等相关内容,今天继续讲解动画相关内容和知识点,仅供学习分享使用,如有不足之处,还请指正。
什么是动画?
动画是快速循环播放一系列图像(其中每个图像与下一个图像略微不同)给人造成的一种幻觉。当图像播放速度超过了人眼识别的速度,就会感觉这些图像形成了一个连贯的变化的场景。在电影中,摄像机每秒钟拍摄许多照片(每一张成为一帧),便可给人造成这种错觉。不同的帧速率会影响视频的流畅度和清晰度。常见的帧速率包括24帧/秒、25帧/秒、30帧/秒等,这些速率各有其适用场景和特点:
- 24帧/秒:这是电影行业标准的帧速率,尤其在拍摄无声电影时期,24帧/秒被广泛采用以节省胶片。尽管如此,24帧/秒在今天仍然被一些艺术家和独立电影制作人使用,以追求特定的视觉效果。
- 25帧/秒:适用于PAL制式,主要在欧洲和一些使用50Hz交流电的地区(如中国)使用。这种帧速率能提供流畅的视频播放,适用于大多数日常视频拍摄。
- 30帧/秒:属于NTSC制式,主要在美国和日本等使用60Hz交流电的地区使用。30帧/秒提供了与25帧/秒相似的流畅度,但在60Hz的地区更为常见。
虽然理论上高帧速率(如100帧/秒甚至更高)能提供更流畅的画面,但在实际拍摄中,高帧速率的采用受到设备能力、存储空间和后期处理成本的限制。因此,在选择帧速率时,需要综合考虑技术可行性、艺术效果和成本等因素。
属性动画系统
在WPF中,通过对对象的个别属性应用动画,可以使控件产生动画效果。如:若要使UI元素变大缩小,可以对其Width和Height属性进行动画处理;若要使UI对象从视野中消失或出现,可以对Opacity属性进行动画处理。若要使属性具有动画功能,属性必须满足以下三个要求:
- 属性必须是依赖属性。
- 属性必须派生自DependencyObject,并实现IAnimatable接口类。
- 必须存在可兼容的动画类型。
由于UIElement类实现IAnimatable接口,而FramworkElement又派生自UIElement,所以大部分的UI控件都包含IAnimatable属性的对象。如Button,TabControl,Panel和Shape等,且大多数属性都是依赖属性。
属性动画
如果要实现一个Rectangle元素从视野中逐渐消失,然后再次出现,并循环播放,应该怎么实现呢?
- 创建双精度值动画:首先UI元素从视野中消失的一种方法是对Opacity属性进行动画处理,而Opacity是[0,1]的double类型的值,因此可以创建一个双精度值动画(DoubleAnimation)。双精度值动画主要用户创建两个double类型值之间的转换,可以通过指定DoubleAnimation的起始值(From),终止值(To)。Opacity属性0表示完全不可见,1表示完全可见。若要使UI元素从不透明到透明的完整过渡,可以设置DoubleAnimation的From值为1.0,To设置为0。
- 设置动画时长:动画需要在多长的时间内完成,可以通过设置DoubleAnimation的Duration属性,Duration属性在XAML中设置格式为HH:mm:ss,在C#中Duration接收TimeSpan类型的参数。
- 设置动画反向执行:动画完成后,是否恢复初始状态,可以通过设置AutoReverse属性来完成,其中true表示恢复到初始状态,false表示停留在结束状态。
- 设置重复执行:动画是否重复执行,可以通过设置RepeatBehavior属性来完成。可指定重复之行的次数,或时长,如果设置为Forever,则永久执行。
- 创建故事板:动画创建好以后,需要装填到故事板(Storyboard)并使用TargetName和TargetPropery属性来指定动画应用的目标对象和属性。
- 设置触发事件:通常情况下,可以将开始故事板(BeginStoryboard)与事件触发器(EventTrigger)进行关联。并添加到EventTrigger的Actions中,并指定RoutedEvent属性设置启动Storyboard的路由事件。
属性动画完整示例如下所示:
<StackPanel Margin="10">
<Rectangle Name="MyRectangle" Width="100" Height="100" Fill="Blue">
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="MyRectangle" Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:5"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</StackPanel>
上述代码在C#中实现,如下所示:
StackPanel panel = new StackPanel();
panel.Margin = new Thickness(10);
Rectangle rectangle = new Rectangle();
rectangle.Name = "rectangle";
this.RegisterName(rectangle.Name, rectangle);
rectangle.Width = 100;
rectangle.Height = 100;
rectangle.Fill = Brushes.Blue;
DoubleAnimation animation = new DoubleAnimation();
animation.From = 1.0;
animation.To = 0.0;
animation.Duration = new Duration(TimeSpan.FromSeconds(5));
animation.AutoReverse = true;
animation.RepeatBehavior = RepeatBehavior.Forever;
var storyboard = new Storyboard();
storyboard.Children.Add(animation);
Storyboard.SetTargetName(animation, rectangle.Name);
Storyboard.SetTargetProperty(animation, new PropertyPath(Rectangle.OpacityProperty));
rectangle.Loaded += new RoutedEventHandler((sender,e) =>{
storyboard.Begin(this);
});
panel.Children.Add(rectangle);
this.Content = panel;
动画类型
不同的属性值具有不同的动画类型,如果是double类型的属性(如:width,height,opacity等)进行动画处理,则可以使用双精度动画(DoubleAntmation);如果是Point类似的属性,则可以使用Point动画(PonitAnimation);如果是颜色类型的属性,则可以使用ColorAnitmation。这些类型的动画位于System.Windows.Media.Animation命名空间,且都遵循“<类型>Animation”格式的命名约定。具体如下所示:
- <类型>Animation,这些动画称为“From/To/By”或“基本”动画,它们在起始值和目标值之间进行动画处理,或者通过将偏移量值与其起始值相加来进行动画处理。
-
若要指定起始值,请设置动画的“From”属性。
-
若要指定终止值,请设置动画的“To”属性。
-
若要指定偏移量值,请设置动画的“By”属性。
-
- <类型>AnimationUsingKeyFrames,关键帧动画的功能比“From/To/By”动画的功能更强大,因为可以指定任意多个目标值,甚至可以控制它们的插值方法。 某些类型只能用关键帧动画进行动画处理。 关键帧动画概述中详细描述了关键帧动画。
- <类型>AnimationUsingPath,路径动画支持使用几何路径来生成动画值。
- <类型>AnimationBase,在实现时对 <类型> 值进行动画处理的抽象类。 此类用作 <类型>Animation 和 <类型>AnimationUsingKeyFrames 类的基类。 只有在想要创建自己的自定义动画时,才需要直接处理这些类。 否则,请使用 <类型>Animation 或 KeyFrame<类型>Animation。
下表显示了一些常用动画类型以及一些与这些类型一起使用的属性。
属性类型 | 对应的基本动画 | 对应的关键帧动画 | 对应的路径动画 | 示例 | ||||||||||||
Color | ColorAnimation | ColorAnimationUsingKeyFrames | 无 | 对 SolidColorBrush 或 GradientStop 的 Color 进行动画处理。 | ||||||||||||
Double | DoubleAnimation | DoubleAnimationUsingKeyFrames | DoubleAnimationUsingPath | 对 DockPanel 的 Width 或 Button 的 Height 进行动画处理。 | ||||||||||||
Point | PointAnimation | PointAnimationUsingKeyFrames | PointAnimationUsingPath | 对 EllipseGeometry 的 Center 位置进行动画处理。 | ||||||||||||
String | 无 | StringAnimationUsingKeyFrames | 无 | 对 TextBlock 的 Text 或 Button 的 Content 进行动画处理。 | ||||||||||||
时间线所有的动画类型均继承自Timeline类。所以所有的动画都是专用类型的时间线。Timeline定义一个时间段,通过Timeline的相关属性,可以指定时间线的计时方式,三个经常使用的计时属性分别为Duration,AutoReverse,和RepeatBehavior。
关键帧动画
与From/To/By动画类似,关键帧动画对目标类型的属性进行动画处理。它通过Duration值属性在目标值之间创建过渡。但是From/To/By动画可以在两个值之间创建过渡,而单个关键帧动画则可以在任意数量的目标值之间创建过渡。关键帧动画没有设置其目标值所需要的From,To,By属性。关键帧动画的目标值使用关键帧对象进行定义,因此称之为“关键帧动画”。动画启动后,在各个关键帧之间进行过渡。 关键帧动画创建步骤:
以下示例使用 DoubleAnimationUsingKeyFrames 对 Rectangle 元素进行四个不同位置的动画处理。
关键帧动画类位于System.Windows.Media.Animation命名空间,且都遵循“<类型>AnimationUsingKeyFrames”格式的命名约定。关键帧动画支持三种不同的插值类型,因此关键帧定义格式遵循如下规则“<InterpolationMethod><Type>KeyFrame”,其中 <InterpolationMethod> 是关键帧使用的内插方法,<Type> 是类进行动画处理的值的类型。 例如,可以针对 DoubleAnimationUsingKeyFrames 使用三种关键帧类型:DiscreteDoubleKeyFrame(离散内插关键帧)、LinearDoubleKeyFrame(线性内插关键帧) 和 SplineDoubleKeyFrame(曲线内插关键帧)。 关键帧的主要目的是定义KeyTime和Value值。
关键帧动画开始后,会按关键帧的 KeyTime 属性定义的顺序来循环访问其关键帧。
注意:KeyTime指定方式可以是“小时:分钟:秒”的Timespan方式,也可以是百分比方式(该值必须大于或等于 0 并且小于或等于 100%)。
路径动画
路径动画是一种使用PathGeometry作为输入的动画时间线(AnimationTimeline),可以定义一个几何路径并使用它来设置路径动画的PathGeometry属性,而不是使用From,To,By属性或使用关键帧。路径动画运行时,会从路径中读取x,y和角度信息并使用该信息生成其输出。路径动画对沿着复杂路径的对象进行动画处理非常有用。不同的属性值类型,对应不同的路径动画类型。 路径动画类属于 System.Windows.Media.Animation 命名空间,并使用以下命名约定: <Type> 其中 <Type> 为该类进行动画处理的值的类型。常见的路径动画如下表所示:
|