教程9:动画教程
动画教程
动画功能使向应用程序或组件添加动态效果非常简单。动画可能并不适合每个软件,但是在许多情况下,动画的合理使用可以改善用户的观看体验,因此可以从中受益。当通过Microsoft Expression Blend等设计工具进行公开时,noesisGUI的动画支持将提供与Adobe Flash类似的功能。但是,由于它是API的核心部分,因此非常简单,因此无需借助此类工具即可轻松创建各种动画。
在本教程中,我们演示了如何创建一些简单的动画来使您的界面栩栩如生。
XAML中的动画
我们可以从屏幕中间的一个简单矩形开始。
AnimationTutorialImg1.jpg<Canvas
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="100" Width="500">
<Rectangle Width="100" Height="60" Margin="60" Fill="YellowGreen"/>
</Canvas>
在XAML中使用Storyboard对象指定了动画。甲故事板定义了将被施加到接口随时间的元素的属性修改的时间线。但是,应该将它们放置在哪里才能被解雇?动画可以响应事件(例如按钮单击)而开始。因此,下一步应该是在我们的示例中添加一个按钮:
AnimationTutorialImg2.jpg <Canvas
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="100" Width="500">
<Rectangle Width="100" Height="60" Margin="60" Fill="YellowGreen"/>
<Button Content="Start Animation" Margin="10" HorizontalAlignment="Left" VerticalAlignment="Top"/>
</Canvas>
每个控件都可以定义一组响应路由事件而执行的动作。它们称为事件触发器,可以在任何控件的Triggers属性中指定。因此,如果要在单击示例中的按钮时启动动画,则应将以下代码添加到XAML:
<Canvas
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="100" Width="500">
<Rectangle Width="100" Height="60" Margin="60" Fill="YellowGreen"/>
<Button Content="Start Animation" Margin="10" HorizontalAlignment="Left" VerticalAlignment="Top">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click"/>
</Button.Triggers>
</Button>
</Canvas>
启动动画的动作由BeginStoryboard类表示,它定义了一个简单的Storyboard属性,在其中指定了动画。
<Canvas
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="100" Width="500">
<Rectangle Width="100" Height="60" Margin="60" Fill="YellowGreen"/>
<Button Content="Start Animation" Margin="10" HorizontalAlignment="Left" VerticalAlignment="Top">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<!-- Storyboard property is the content property of BeginStoryboard -->
<!-- class, so we don't need to make it explicit in the code -->
<Storyboard />
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</Canvas>
我们可以添加的第一个动画可以是在屏幕内移动矩形。我们可以通过将TranslateTransform应用于矩形的RenderTransform属性来实现。但是我们需要一种从动画时间轴中引用矩形的方法,这显然是通过设置矩形元素的名称来完成的。现在的示例如下所示:
<Canvas
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="100" Width="500">
<Rectangle x:Name="Rect" Width="100" Height="60" Margin="60" Fill="YellowGreen" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<TranslateTransform X="0" Y="0"/>
</Rectangle.RenderTransform>
</Rectangle>
<Button Content="Start Animation" Margin="10" HorizontalAlignment="Left" VerticalAlignment="Top">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard TargetName="Rect"
TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)">
<DoubleAnimation Duration="0:0:1" From="0" To="50"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</Canvas>
现在,当用户单击按钮时,绿色矩形将在一秒钟内向右水平移动50个像素。您可以阅读动画参考以获取有关可用于自定义动画的属性的完整信息(开始时间,自动反转,重复行为等)。
如果要为同一对象或来自不同对象的多个属性设置动画,则可以受益于TargetProperty和TargetName属性的附加行为。例如,要在移动矩形时淡出矩形,我们可以添加以下内容:
<Canvas
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="100" Width="500">
<Rectangle x:Name="Rect" Width="100" Height="60" Margin="60" Fill="YellowGreen" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<TranslateTransform X="0" Y="0"/>
</Rectangle.RenderTransform>
</Rectangle>
<Button Content="Start Animation" Margin="10" HorizontalAlignment="Left" VerticalAlignment="Top">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:1" From="0" To="50"
Storyboard.TargetName="Rect"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)"/>
<DoubleAnimation Duration="0:0:1" From="1" To="0"
Storyboard.TargetName="Rect"
Storyboard.TargetProperty="(Shape.Fill).(Brush.Opacity)"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</Canvas>
AnimationTutorialImg3.jpg
注意
加载XAML时,动画也可以自动启动。这可以通过使用FrameworkElement.Loaded路由事件而不是响应Button.Click事件来实现。
关键帧动画
普通动画类仅支持从一个值到另一值的线性插值(或由于AccelerationRatio和DecelerationRatio属性而限制了非线性插值的有限形式)。如果要表示更复杂的动画,可以指定关键帧,这些关键帧在特定时间提供特定值。使用关键帧需要启用关键帧的动画类。例如,Double Animation与所有其他动画类一样,都有一个名为DoubleAnimationUsingKeyFrames的伴随类。
除了From,To和By属性外,关键帧动画类具有与其对应的相同的属性和事件。相反,它们具有KeyFrames集合,该集合可以保存特定于要设置动画类型的关键帧实例。共有三种关键帧:线性,样条曲线和离散。
线性关键帧
在KeyFrame值之间执行线性插值。
<Canvas
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="100" Width="500">
<Rectangle x:Name="Rect" Width="100" Height="60" Margin="60" Fill="YellowGreen" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<TranslateTransform X="0" Y="0"/>
</Rectangle.RenderTransform>
</Rectangle>
<Button Content="Start Animation" Margin="10" HorizontalAlignment="Left" VerticalAlignment="Top">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="Rect"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)">
<LinearDoubleKeyFrame Value="0" KeyTime="0:0:0"/>
<LinearDoubleKeyFrame Value="50" KeyTime="0:0:1"/>
<LinearDoubleKeyFrame Value="-20" KeyTime="0:0:2"/>
<LinearDoubleKeyFrame Value="80" KeyTime="0:0:3"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</Canvas>
样条关键帧
样条关键帧类具有一个额外的KeySpline属性,该属性将自己与线性类区分开。可以将KeySpline设置为KeySpline对象的实例,该实例将所需的运动描述为三次贝塞尔曲线。KeySpline具有Point类型的两个属性,它们代表曲线的控制点。
<Canvas
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="100" Width="500">
<Rectangle x:Name="Rect" Width="100" Height="60" Margin="60" Fill="YellowGreen" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<TranslateTransform X="0" Y="0"/>
</Rectangle.RenderTransform>
</Rectangle>
<Button Content="Start Animation" Margin="10" HorizontalAlignment="Left" VerticalAlignment="Top">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="Rect"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)">
<SplineDoubleKeyFrame KeySpline="0,1 1,0" Value="0" KeyTime="0:0:0"/>
<SplineDoubleKeyFrame KeySpline="0,1 1,0" Value="50" KeyTime="0:0:1"/>
<SplineDoubleKeyFrame KeySpline="0,1 1,0" Value="-20" KeyTime="0:0:2"/>
<SplineDoubleKeyFrame KeySpline="0,1 1,0" Value="80" KeyTime="0:0:3"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</Canvas>
离散关键帧
一个离散关键帧只是表示不插应该从一个关键帧来完成。
<Canvas
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="100" Width="500">
<Rectangle x:Name="Rect" Width="100" Height="60" Margin="60" Fill="YellowGreen" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<TranslateTransform X="0" Y="0"/>
</Rectangle.RenderTransform>
</Rectangle>
<Button Content="Start Animation" Margin="10" HorizontalAlignment="Left" VerticalAlignment="Top">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="Rect"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)">
<DiscreteDoubleKeyFrame Value="0" KeyTime="0:0:0"/>
<DiscreteDoubleKeyFrame Value="50" KeyTime="0:0:1"/>
<DiscreteDoubleKeyFrame Value="-20" KeyTime="0:0:2"/>
<DiscreteDoubleKeyFrame Value="80" KeyTime="0:0:3"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</Canvas>
注意
每个关键帧实例都可以给出一个特定的值以及应用该值的时间。但是,设置KeyTime是可选的。如果省略,则动画系统会假定关键帧出现在周围关键帧的中间。如果在所有关键帧上都省略KeyTime,则它们在动画期间的间隔是均匀的。
缓动功能
缓动功能使您可以将自定义数学公式应用于动画。例如,您可能希望对象真实地弹跳或表现得像在弹簧上一样。您可以使用KeyFrame甚至是From / To / By动画来近似这些效果,但是这需要大量的工作,并且动画的准确性不如数学公式。
除了通过继承EasingFunctionBase创建自己的自定义缓动函数外,还可以使用动画系统提供的几种缓动函数之一来创建通用效果。
<Canvas
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="100" Width="500">
<Rectangle x:Name="Rect" Width="100" Height="60" Margin="60" Fill="YellowGreen" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<TranslateTransform X="0" Y="0"/>
</Rectangle.RenderTransform>
</Rectangle>
<Button Content="Start Animation" Margin="10" HorizontalAlignment="Left" VerticalAlignment="Top">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:1" From="1" To="0"
Storyboard.TargetName="Rect"
Storyboard.TargetProperty="(Shape.Fill).(Brush.Opacity)">
<DoubleAnimation.EasingFunction>
<SineEase EasingMode="EaseInOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</Canvas>