WPF可以在代码中编写动画的行为,也可以在XAML中编写,我们这里只介绍XAML中的动画效果。在XAML中动画是通过叫做故事版的元属来描述,你可以设置界面元素的属性变化来产生动画的效果,这些属性可以是颜色、透明度、位置、大小尺寸等。动画的类型有ColorAnimation、DoubleAnimation、PointAnimation等。它们通过一个TimeLine的对象来实现动画效果,下面是一个DoubleAnimation的动画描述:
<DoubleAnimation From="1.0" To="0.0"
TargetProperty="(Rectangle.Opacity)"
Duration="0:0:1"
/>
DoubleAnimation动画,表示属性的状态在两个值之间变化,通过指定From和To等属性。上面的代码定义了对一个矩形对象的透明度实现动画效果,透明度的值从1变化到0, Duration属性设置完成动画的时间跨度,这里设置为1秒。前面提到,动画的描述必须放置在故事板中:
当一个矩形的透明度从1变到0,那么这个矩形就看不见了,如果我们需要恢复到原来的透明度,只要把透明度恢复到1,通过设置AutoReverse为True就可以达到目的,如果我们要一直不停的重复动画效果,可以设置RepeatBehavior为Forever,代码如下:
<Storyboard>
<DoubleAnimation From="1.0" To="0.0"
TargetProperty="(Rectangle.Opacity)"
Duration="0:0:1"
AutoReverse="True" RepeatBehavior="Forever"/>
</Storyboard>
动画的触发是通过一个称作触发器的元属,触发器通常由事件来触发:
动画的触发是通过一个称作触发器的元属,触发器通常由事件来触发:<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<Storyboard><DoubleAnimation Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="(Rectangle.Opacity)"
From="1.0" To="0.0" Duration="0:0:1"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
上面代码描述了完整的一个动画过程,注意到动画的触发事件设置为Rectangle.Loaded事件。最后我们还观看一下动画的效果:
上面代码描述了完整的一个动画过程,注意到动画的触发事件设置为 Rectangle.Loaded 事件。最后我们还观看一下动画的效果:用下面的代码替换上一次例子的Viewport3D元属:
<DockPanel Margin="10">
<Rectangle Name="MyRectangle" Width="100" Height="100" Fill="Blue">
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<EventTrigger RoutedEvent="Rectangle.Loaded"><BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="(Rectangle.Opacity)"
From="1.0" To="0.0" Duration="0:0:1"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</DockPanel>
如果一切正常的话,你将看到蓝色的矩形的透明度循环地发生着变化。
动画的控制可以通过故事板的几个事件来操作,它们有:PauseStoryboard, ResumeStoryboard, SetStoryboardSpeedRatio, SkipStoryboardToFill, StopStoryboard。
下面的代码演示了这些操作(通过对例子代码的修改):
<DockPanel xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"
>
<DockPanel.Resources>
<Style TargetType="{x:Type Menu}" >
<Setter Property="FontSize" Value="12" />
<Setter Property="FontFamily" Value="Verdana" />
<Setter Property="Background" Value="Yellow" />
</Style>
<Style x:Key="Header" TargetType="{x:Type StackPanel}">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0" Color="#0000FF" />
<GradientStop Offset="0.5" Color="#FFFFFF" />
<GradientStop Offset="1" Color="#0000FF" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Black" />
<Setter Property="Margin" Value="10,10,10,0"/>
<Setter Property="DockPanel.Dock" Value="Top"/>
<Setter Property="Height" Value="25"/>
<Setter Property="Width" Value="100"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="FontFamily" Value="Verdana" />
<Setter Property="Background">
<Setter.Value>
<RadialGradientBrush>
<RadialGradientBrush.GradientStops>
<GradientStop Offset="0" Color="#FFFFFF" />
<GradientStop Offset="2" Color="#0000FF" />
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
</Setter.Value>
</Setter>
</Style>
<TransformGroup x:Key="MyTransformGroupResource">
<ScaleTransform />
<RotateTransform CenterX="50" CenterY="50"/>
</TransformGroup>
</DockPanel.Resources>
<StackPanel Name="Header" DockPanel.Dock="Top" Height="100" Style="{StaticResource Header}"/>
<Menu DockPanel.Dock="Top">
<MenuItem Header="File"/>
<MenuItem Header="Eidt" />
<MenuItem Header="View" />
<MenuItem Header="Tools"/>
<MenuItem Header="Help"/>
</Menu>
<StackPanel DockPanel.Dock="Bottom" Height="40" Background="DarkBlue" />
<StackPanel DockPanel.Dock="Left" Width="120" Background="LightGray">
<Button Name="BeginButton">
Begin</Button>
<Button Name="PauseButton">
Pause</Button>
<Button Name="ResumeButton">
Resume</Button>
<Button Name="SkipButton">
Skip to fill</Button>
<Button Name="StopButton">
Stop</Button>
<StackPanel.Triggers>
<EventTrigger RoutedEvent="Button.Click" SourceName="BeginButton">
<BeginStoryboard Name="MyStoryBoard">
<Storyboard >
<DoubleAnimation Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="(Rectangle.Opacity)"
From="1.0" To="0.0" Duration="0:0:5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Button.Click" SourceName="PauseButton">
<PauseStoryboard BeginStoryboardName="MyStoryBoard" />
</EventTrigger>
<EventTrigger RoutedEvent="Button.Click" SourceName="ResumeButton">
<ResumeStoryboard BeginStoryboardName="MyStoryBoard" />
</EventTrigger>
<EventTrigger RoutedEvent="Button.Click" SourceName="SkipButton">
<SkipStoryboardToFill BeginStoryboardName="MyStoryBoard" />
</EventTrigger>
<EventTrigger RoutedEvent="Button.Click" SourceName="StopButton">
<StopStoryboard BeginStoryboardName="MyStoryBoard" />
</EventTrigger>
</StackPanel.Triggers>
</StackPanel>
<DockPanel Margin="10">
<Rectangle Name="MyRectangle" Width="100" Height="100" Fill="Blue"
RenderTransform="{StaticResource MyTransformGroupResource}"
>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="RenderTransform.Children[1].Angle"
From="0" To="360" Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
<StackPanel Margin="20">
<Rectangle Name="nonAcceleratedOrDeceleratedRectangle" Fill="#9933FF"
Width="10" Height="20" HorizontalAlignment="Left" />
<Rectangle Name="acceleratedRectangle" Fill="#3333FF"
Width="10" Height="20" HorizontalAlignment="Left" />
<Rectangle Name="deceleratedRectangle" Fill="#33FF66"
Width="10" Height="20" HorizontalAlignment="Left" />
<Rectangle Name="acceleratedAndDeceleratedRectangle" Fill="#CCFF33"
Width="10" Height="20" HorizontalAlignment="Left" />
<Ellipse Width="30" Height="30" Fill="Red" >
<Ellipse.RenderTransform>
<TranslateTransform x:Name="MyAnimatedTransform" X="10" Y="100" />
</Ellipse.RenderTransform>
</Ellipse>
<!-- Create a button to start the animations. -->
<Button Name="myRestartButton" Margin="0,30,0,0" HorizontalAlignment="Left">Restart Animations
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<!-- Creates an animation without acceleration or deceleration for comparison. -->
<DoubleAnimation
Storyboard.TargetName="nonAcceleratedOrDeceleratedRectangle"
Storyboard.TargetProperty="(Rectangle.Width)"
Duration="0:0:10" From="20" To="400" />
<!-- Creates an animation that accelerates through 40% of its duration. -->
<DoubleAnimation
Storyboard.TargetName="acceleratedRectangle"
Storyboard.TargetProperty="(Rectangle.Width)"
AccelerationRatio="0.4" Duration="0:0:10" From="20" To="400" />
<!-- Creates an animation that decelerates through 60% of its duration. -->
<DoubleAnimation
Storyboard.TargetName="deceleratedRectangle"
Storyboard.TargetProperty="(Rectangle.Width)"
DecelerationRatio="0.6" Duration="0:0:10" From="20" To="400" />
<!-- Creates an animation that accelerates through 40% of its duration and
decelerates through the 60% of its duration. -->
<DoubleAnimation
Storyboard.TargetName="acceleratedAndDeceleratedRectangle"
Storyboard.TargetProperty="(Rectangle.Width)"
AccelerationRatio="0.4" DecelerationRatio="0.6" Duration="0:0:10" From="20" To="400" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard Name="MyBeginStoryboard">
<Storyboard>
<!-- Animates the circle horizotally along the path. -->
<DoubleAnimationUsingPath
Storyboard.TargetName="MyAnimatedTransform"
Storyboard.TargetProperty="X"
PathGeometry="M 10,100 C35,0 135,0 160,100 S285,200 310,100"
Source="X"
Duration="0:0:5"
RepeatBehavior="Forever" AutoReverse="True" />
<!-- Animates the cube vertically along the path. -->
<DoubleAnimationUsingPath
Storyboard.TargetName="MyAnimatedTransform"
Storyboard.TargetProperty="Y"
PathGeometry="M 10,100 C35,0 135,0 160,100 S285,200 310,100"
Source="Y"
Duration="0:0:5"
RepeatBehavior="Forever" AutoReverse="True" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</StackPanel>
</DockPanel>
</DockPanel>
上面例子中,我们还演示了某些其他动画的效果。下一次我们将演示WPF的文档功能。
WPF体验(一)
WPF体验(二)
WPF体验(三)
WPF体验(四)