IT教程 ·

【WPF学习】第五十三章 动画类型回首

Scrum 敏捷实践中的三大角色

建立动画面对的第一个应战是为动画挑选准确的属性。希冀的结果(比方,在窗口中挪动元素)与须要运用的属性(在这类状况下是Canvas.Left和Canvas.Top属性)之间的关联并不老是很直观。下面是一些指点准绳:

  •   假如愿望运用动画来使元素显现和消逝,不要运用Visibility属性(该属性只能在完全可见和完全不可见之间举行切换)。应改用Opacity属性淡入或淡出元素。
  •   假如愿望动态转变元素的位置,可斟酌运用Canvas面板。它供应了最直接的属性(Canvas.Left及Canvas.Top),而且开支最小。另外,也可运用动画属性在其他规划容器中取得相似结果。比方,可经由过程运用ThicknessAnimation类动态转变Margin和Padding等属性,还可动态转变Grid控件中的MinWidth或MinHeight属性、一列或一行。
  •   动画最经常使用的属性是衬着变更。可运用变更挪动或翻转元素(TranslateTransform)、扭转元素(RotateTransform)、缩放或歪曲元素(ScaleTransform)等。经由过程细致地运用变更,偶然可防止在动画中硬编码尺寸和位置。它们也绕过了WPF规划体系,比直接作用于元素大小或位置的其他要领速率更快。
  •   动态转变元素外表的较好要领是修正画刷属性。可运用ColorAnimation转变色彩或其他动画对象来变更更庞杂画刷的属性,如渐变中的偏移。

接下来的示例演示了怎样动态转变变更和画刷,以及怎样运用更多的一些动画范例。还将议论怎样运用关键帧建立多段动画、怎样建立基于途径的动画和基于帧的动画。

一、动态变更

变更供应了自定义元素的最强大体式格局之一。当运用变更时,不只是转变元素的边境,而且会挪动、翻转、歪曲、拉伸、放大、削减或扭转元素的全部可视化表面。比方,可经由过程ScaleTransform动态转变按钮的尺寸,这会转变全部按钮的尺寸,包括按钮的边框及其内部的内容。这类结果比动态转变Width和Height属性或转变文本的Fontsize属性给人的印象更深切。

前面章节相识到,每一个元素都能以两种差别的体式格局运用变更:RenderTransform属性和LayoutTransform属性。RenderTransform效力更高,由于是在规划以后运用变更而且勇于变更终究的衬着输出。LayoutTransform在规划前运用,从而其他控件须要重新排列以顺应变更。转变LayoutTransform属性会激发新的规划操纵(除非在Canvas面板上运用元素,在这类状况下,RenderTransform和LayoutTransform的结果雷同)。

为在动画中运用变更,第一步是定义变更(动画可转变已存在的变更,但不能建立新的变更)。比方,假定愿望使按钮扭转,此时须要运用RotateTransform对象:

<Button Content="A Button">
    <RenderTransform>
        <RotateTransform></RotateTransform>
    </RenderTransform>
</Button>

现在当将鼠标挪动到按钮上时,下面的事宜触发器就会扭转按钮。运用的目的属性是RenderTransform.Angle——换句话说,读取按钮的RenderTransform属性并修正个中定义的RotateTransform对象的Angle属性。事实上,RenderTransform属性可包括种种差别的变更对象,每种变更对象的属性各不雷同,这不会引起问题。只需运用的变更具有Angle属性,这个触发器就可以事情:

<EventTrigger RoutedEvent="Button.MouseEnter">
    <EventTrigger.Actions>
          <BeginStoryboard Name="rotateStoryboardBegin">
               <Storyboard>
                     <DoubleAnimation Storyboard.TargetProperty="RenderTransform.Angle"
                 To="360" Duration="0:0:0.8" RepeatBehavior="Forever"></DoubleAnimation>
                </Storyboard>
           </BeginStoryboard>
     </EventTrigger.Actions>
</EventTrigger>

按钮在0.8秒得时候内扭转一周而且延续扭转。当按钮扭转时仍完全可用——比方,可单击按钮并处置惩罚Click事宜。

为保证按钮绕个中间扭转(而不是绕左上角扭转),须要按以下体式格局设置RenderTransformOrigin属性:

<Button RenderTransformOrigin="0.5,0.5"/>

请记着,RenderTransformOrigin属性运用0~1的相对单元,所以0.5示意中点。

为住手扭转,可运用第二个触发器响应MouseLeave事宜。这是,可删除实行扭转的故事板,但这会致使按钮一步伐回到它本来的位置。更好的要领是入手下手第二个动画,用它替换第一个动画。这个动画疏忽To和From属性,这意味着它无缝地再0.2秒得时候内将按钮扭转回原始方向:

<EventTrigger RoutedEvent="Button.MouseLeave">
    <EventTrigger.Actions>
         <BeginStoryboard>
              <Storyboard>
                  <DoubleAnimation Storyboard.TargetProperty="RenderTransform.Angle"
                   Duration="0:0:0.2"></DoubleAnimation>
               </Storyboard>
          </BeginStoryboard>
    </EventTrigger.Actions>
</EventTrigger>

为建立扭转的按钮,须要为Button.Triggers鸠合增添这两个触发器。或将它们(以及变更)放到一个款式中,并依据须要为多个按钮运用这个款式。比方,下面的窗口标记充满了下图中显现的“能扭转的”按钮:

【WPF学习】第五十三章 动画类型回首 IT教程 第1张
【WPF学习】第五十三章 动画类型回首 IT教程 第2张

<Window x:Class="Animation.RotateButton"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="RotateButton" Height="300" Width="300">
    <Window.Resources>

        <Style TargetType="{x:Type Button}">
            <Setter Property="HorizontalAlignment" Value="Center"></Setter>
            <Setter Property="RenderTransformOrigin" Value="0.5,0.5"></Setter>
            <Setter Property="Padding" Value="20,15"></Setter>
            <Setter Property="Margin" Value="2"></Setter>
            <Setter Property="RenderTransform">
                <Setter.Value>
                    <RotateTransform></RotateTransform>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <EventTrigger RoutedEvent="Button.MouseEnter">
                    <EventTrigger.Actions>
                        <BeginStoryboard Name="rotateStoryboardBegin">
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="RenderTransform.Angle"
                 To="360" Duration="0:0:0.8" RepeatBehavior="Forever"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
                <EventTrigger RoutedEvent="Button.MouseLeave">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="RenderTransform.Angle"
                   Duration="0:0:0.2"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
            </Style.Triggers>
        </Style>

    </Window.Resources>
    <StackPanel Margin="5" Button.Click="cmd_Clicked">
        <Button>One</Button>
        <Button>Two</Button>
        <Button>Three</Button>
        <Button>Four</Button>
        <TextBlock Name="lbl" Margin="5"></TextBlock>
    </StackPanel>
</Window>

RotateButton

在单击任何按钮时,都会在TextBlock元素中显现一条信息。

【WPF学习】第五十三章 动画类型回首 IT教程 第3张

这个示例还未剖析衬着变更和规划变更之间的区分供应了绝佳的时机。假如修正代码可运用LayoutTransform属性,那末会发明当扭转个中一个按钮时,其他按钮会被推离本来的位置。比方,假如扭转最上面的按钮,下面的按钮会上下跳动以避开顶部的按钮。

【WPF学习】第五十三章 动画类型回首 IT教程 第1张
【WPF学习】第五十三章 动画类型回首 IT教程 第2张

<Window x:Class="Animation.RotateButtonWithLayout"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="RotateButtonWithLayout" Height="300" Width="300">
    <Window.Resources>

        <Style TargetType="{x:Type Button}">
            <Setter Property="HorizontalAlignment" Value="Center"></Setter>
            <Setter Property="RenderTransformOrigin" Value="0.5,0.5"></Setter>
            <Setter Property="Padding" Value="20,15"></Setter>
            <Setter Property="Margin" Value="2"></Setter>
            <Setter Property="LayoutTransform">
                <Setter.Value>
                    <RotateTransform></RotateTransform>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <EventTrigger RoutedEvent="Button.MouseEnter">
                    <EventTrigger.Actions>
                        <BeginStoryboard Name="rotateStoryboardBegin">
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="LayoutTransform.Angle"
                 To="360" Duration="0:0:0.8" RepeatBehavior="Forever"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
                <EventTrigger RoutedEvent="Button.MouseLeave">
                    <EventTrigger.Actions>
                        <!-- <RemoveStoryboard BeginStoryboardName="rotateStoryboardBegin"></RemoveStoryboard> -->
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="LayoutTransform.Angle"
                   Duration="0:0:0.2"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
            </Style.Triggers>
        </Style>

    </Window.Resources>
    <StackPanel Margin="5" Button.Click="cmd_Clicked">
        <Button>One</Button>
        <Button>Two</Button>
        <Button>Three</Button>
        <Button>Four</Button>
        <TextBlock Name="lbl" Margin="5"></TextBlock>
    </StackPanel>
</Window>

RotateButtonWithLayout

【WPF学习】第五十三章 动画类型回首 IT教程 第6张

动态转变多个变更

可很轻易地组合运用变更。实际上这是很轻易——只须要运用TransformGroup对象设置LayoutTransform或RenderTransform属性即可。可依据须要在TransformGroup对象中嵌套恣意多个变更。

下图显现了一个运用两个变更建立的风趣结果。文档窗口刚入手下手作为主窗口左上角的小缩略图。当文档窗口显现时,内容扭转、扩大并疾速淡入到试图中,从概念上讲,这与最大化窗口时Windows运用的结果相似。在WPF中,可经由过程变更为一切的元素运用这类技能。

【WPF学习】第五十三章 动画类型回首 IT教程 第7张

为建立这类结果,在以下TransformGroup对象中定义了两个变更,并运用TransformGroup对象设置包括一切内容的Board对象的RenderTransform属性:

<Border.RenderTransform>
     <TransformGroup>
           <ScaleTransform></ScaleTransform>
            <RotateTransform></RotateTransform>
      </TransformGroup>
</Border.RenderTransform>

经由过程指定数字偏移值(0用于起首显现的ScaleTransform对象,1用于接下来显现的RotateTransform对象),动画可与这两个变更对象举行交互。比方,下面的动画放大内容:

<DoubleAnimation Storyboard.TargetName="element"
                                Storyboard.TargetProperty="RenderTransform.Children[0].ScaleX"
                                From="0" To="1" Duration="0:0:2" AccelerationRatio="1"></DoubleAnimation>
<DoubleAnimation Storyboard.TargetName="element"
                                Storyboard.TargetProperty="RenderTransform.Children[0].ScaleY"
                                From="0" To="1" Duration="0:0:2" AccelerationRatio="1"></DoubleAnimation>

下面的动画位于雷同的故事板中,用于扭转内容:

<DoubleAnimation Storyboard.TargetName="element"
                                Storyboard.TargetProperty="RenderTransform.Children[1].Angle"
                                From="70" To="0" Duration="0:0:2" ></DoubleAnimation>

这个动画中的内容比此处显现的内容还多。比方,另有一个同事增添Opacity属性的动画,而且当Borad元素到达最大尺寸时,它短暂地向后"反弹"一下,建立一种更趋天然的结果。为这个动画建立时候线并修正各个动画对象属性须要消耗时候——抱负状况下,可运用诸如Expression Blend的设想东西实行这些使命,而不是经由过程手动编写代码来完成这些使命。以至更好的状况下,只需有第三方开发者将这一逻辑分组到自定义动画中,就可以够重用并依据须要将其运用到对象上(依据现在的状况,可经由过程将Storyboard对象存储为运用程序级的资本,重用这个动画)。

下面是完全的XAML标记:

【WPF学习】第五十三章 动画类型回首 IT教程 第1张
【WPF学习】第五十三章 动画类型回首 IT教程 第2张

<Window x:Class="Animation.ExpandElement"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ExpandElement" Height="423.2" Width="488.8" WindowStartupLocation="CenterScreen">
    <Window.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">
            <EventTrigger.Actions>
                <BeginStoryboard>
                    <Storyboard SpeedRatio="1.5">
                        <DoubleAnimation Storyboard.TargetName="element"
                                Storyboard.TargetProperty="Opacity"
                                From="0.2" To="1" Duration="0:0:2.5"></DoubleAnimation>
                        <DoubleAnimation Storyboard.TargetName="element"
                                Storyboard.TargetProperty="RenderTransform.Children[1].Angle"
                                From="70" To="0" Duration="0:0:2" ></DoubleAnimation>

                        <DoubleAnimation Storyboard.TargetName="element"
                                Storyboard.TargetProperty="RenderTransform.Children[0].ScaleX"
                                From="0" To="1" Duration="0:0:2" AccelerationRatio="1"></DoubleAnimation>
                        <DoubleAnimation Storyboard.TargetName="element"
                                Storyboard.TargetProperty="RenderTransform.Children[0].ScaleY"
                                From="0" To="1" Duration="0:0:2" AccelerationRatio="1"></DoubleAnimation>

                        <DoubleAnimation Storyboard.TargetName="element"
                                            Storyboard.TargetProperty="RenderTransform.Children[0].ScaleX"
                                            To="0.98" BeginTime="0:0:2" Duration="0:0:0.05"  DecelerationRatio="1"></DoubleAnimation>
                        <DoubleAnimation Storyboard.TargetName="element"
                                Storyboard.TargetProperty="RenderTransform.Children[0].ScaleY"
                                To="0.98" BeginTime="0:0:2" Duration="0:0:0.05" DecelerationRatio="1"></DoubleAnimation>
                        <DoubleAnimation Storyboard.TargetName="element"
                                            Storyboard.TargetProperty="RenderTransform.Children[0].ScaleX"
                                            To="1" BeginTime="0:0:2.05" Duration="0:0:0.2"  AccelerationRatio="1"></DoubleAnimation>
                        <DoubleAnimation Storyboard.TargetName="element"
                                Storyboard.TargetProperty="RenderTransform.Children[0].ScaleY"
                                To="1" BeginTime="0:0:2.05" Duration="0:0:0.2" AccelerationRatio="1"></DoubleAnimation>

                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger.Actions>
        </EventTrigger>
    </Window.Triggers>

    <Grid>
        <!--<Button Name="element">
        <Button.Content>Text</Button.Content>
        <Button.RenderTransform>
          <TransformGroup>
            <ScaleTransform ScaleX="0" ScaleY="0"></ScaleTransform>
            <TranslateTransform></TranslateTransform>
            <RotateTransform Angle="90"></RotateTransform>
          </TransformGroup>
        </Button.RenderTransform>
      </Button>-->
        <Border  Name="element" Margin="3" Background="LightGoldenrodYellow"
               BorderBrush="DarkBlue" BorderThickness="2" CornerRadius="5" >
            <Border.RenderTransform>
                <TransformGroup>
                    <ScaleTransform></ScaleTransform>
                    <RotateTransform></RotateTransform>
                </TransformGroup>
            </Border.RenderTransform>
            <FlowDocumentScrollViewer IsToolBarVisible="True">
                <FlowDocument>

                    <Paragraph xml:space="preserve">The <Italic>foof</Italic> feature is indispensable. You can configure the foof feature using the Foof Options dialog box.</Paragraph>
                    <BlockUIContainer>
                        <Button HorizontalAlignment="Left" Padding="5">Open Foof Options</Button>
                    </BlockUIContainer>


                    <Paragraph FontSize="20pt">Largest Cities in the Year 100</Paragraph>
                    <Table>
                        <Table.Columns>
                            <TableColumn Width="*"></TableColumn>
                            <TableColumn Width="3*"></TableColumn>
                            <TableColumn Width="*"></TableColumn>
                        </Table.Columns>

                        <TableRowGroup  >
                            <TableRow FontWeight="Bold" >
                                <TableCell >
                                    <Paragraph>Rank</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>Name</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>Population</Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell>
                                    <Paragraph>1</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>Rome</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>450,000</Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell>
                                    <Paragraph>2</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>Luoyang (Honan), China</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>420,000</Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell>
                                    <Paragraph>3</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>Seleucia (on the Tigris), Iraq</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>250,000</Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell>
                                    <Paragraph>4</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>Alexandria, Egypt</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>250,000</Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell>
                                    <Paragraph>5</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>Antioch, Turkey</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>150,000</Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell>
                                    <Paragraph>6</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>Anuradhapura, Sri Lanka</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>130,000</Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell>
                                    <Paragraph>7</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>Peshawar, Pakistan</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>120,000</Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell>
                                    <Paragraph>8</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>Carthage, Tunisia</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>100,000</Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell>
                                    <Paragraph>9</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>Suzhou, China</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>n/a</Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell>
                                    <Paragraph>10</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>Smyrna, Turkey</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>90,000</Paragraph>
                                </TableCell>
                            </TableRow>
                        </TableRowGroup>
                    </Table>
                </FlowDocument>
            </FlowDocumentScrollViewer>
        </Border>

    </Grid>

</Window>

ExpandElement

这类结果异常有效。比方,可运用该结果将注意力吸收到新的内容——比方用户方才翻开的文件。这类结果大概的变化是无穷无尽的。比方,建立产物目录时,当用户将鼠标悬停在响应的产物名称上时,滑入包括产物细节的面板或将产物图象滚入试图。

二、动态转变画刷

动态转变画刷是WPF动画中的另一种经常使用手艺,和动态变更一样轻易。一样,这类手艺运用适当的动画范例,深切到愿望转变的特定子属性。

下图显现了一个修正RadialGradientBrush画刷的示例。当动画运行时,径向渐变的中间点沿椭圆漂移,从而完成了一种三维结果。同时,外侧的渐变色彩从蓝色变成黑色。

【WPF学习】第五十三章 动画类型回首 IT教程 第10张

为完成这个结果,须要运用两种还没有剖析过的动画范例。ColorAnimation动画在两个色彩之间逐步夹杂,建立一种玄妙的色彩转移结果。PointAnimation动画可将点从一个位置移到另一个位置(本质上与运用自力DoubleAnimation,经由过程线性插值同时修正X坐标和Y坐标是雷同的)。可运用PointAnimation动画转变运用点组织的图形,或许就像这个示例中那样,转变径向渐变中间点的位置。

下面是标记定义了椭圆及其画刷:

<Ellipse Name="ellipse" Margin="5" Grid.Row="1" Stretch="Uniform">
   <Ellipse.Fill>
         <RadialGradientBrush
             RadiusX="1" RadiusY="1" GradientOrigin="0.7,0.3">
                    <GradientStop Color="White" Offset="0" ></GradientStop>
                    <GradientStop Color="Blue" Offset="1" ></GradientStop>
          </RadialGradientBrush>

   </Ellipse.Fill>
</Ellipse>

下面是挪动中间点以及转变第二种色彩的两个动画:

<PointAnimationUsingKeyFrames Storyboard.TargetName="ellipse" Storyboard.TargetProperty="Fill.GradientOrigin"
                                           RepeatBehavior="Forever">
                        <LinearPointKeyFrame Value="0.7,0.3" KeyTime="0:0:0"></LinearPointKeyFrame>
                        <LinearPointKeyFrame Value="0.3,0.7" KeyTime="0:0:5"></LinearPointKeyFrame>
                        <LinearPointKeyFrame Value="0.5,0.9" KeyTime="0:0:8"></LinearPointKeyFrame>
                        <LinearPointKeyFrame Value="0.9,0.6" KeyTime="0:0:10"></LinearPointKeyFrame>
                        <LinearPointKeyFrame Value="0.8,0.2" KeyTime="0:0:12"></LinearPointKeyFrame>
                        <LinearPointKeyFrame Value="0.7,0.3" KeyTime="0:0:14"></LinearPointKeyFrame>

                        <DiscretePointKeyFrame Value="0.7,0.3" KeyTime="0:0:20"></DiscretePointKeyFrame>
                        <DiscretePointKeyFrame Value="0.3,0.7" KeyTime="0:0:25"></DiscretePointKeyFrame>
                        <DiscretePointKeyFrame Value="0.5,0.9" KeyTime="0:0:28"></DiscretePointKeyFrame>
                        <DiscretePointKeyFrame Value="0.9,0.6" KeyTime="0:0:20"></DiscretePointKeyFrame>
                        <DiscretePointKeyFrame Value="0.8,0.2" KeyTime="0:0:22"></DiscretePointKeyFrame>
                        <DiscretePointKeyFrame Value="0.7,0.3" KeyTime="0:0:24"></DiscretePointKeyFrame>
                    </PointAnimationUsingKeyFrames>


                    <ColorAnimation Storyboard.TargetName="ellipse" Storyboard.TargetProperty="Fill.GradientStops[1].Color"
              To="Black"  Duration="0:0:10"
              AutoReverse="True" RepeatBehavior="Forever"></ColorAnimation>

本例网站XAML标记:

【WPF学习】第五十三章 动画类型回首 IT教程 第1张
【WPF学习】第五十三章 动画类型回首 IT教程 第2张

<Window x:Class="Animation.AnimateRadialGradient"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="AnimateRadialGradient" Height="300" Width="300" WindowStartupLocation="CenterScreen">
    <Window.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <PointAnimationUsingKeyFrames Storyboard.TargetName="ellipse" Storyboard.TargetProperty="Fill.GradientOrigin"
                                           RepeatBehavior="Forever">
                        <LinearPointKeyFrame Value="0.7,0.3" KeyTime="0:0:0"></LinearPointKeyFrame>
                        <LinearPointKeyFrame Value="0.3,0.7" KeyTime="0:0:5"></LinearPointKeyFrame>
                        <LinearPointKeyFrame Value="0.5,0.9" KeyTime="0:0:8"></LinearPointKeyFrame>
                        <LinearPointKeyFrame Value="0.9,0.6" KeyTime="0:0:10"></LinearPointKeyFrame>
                        <LinearPointKeyFrame Value="0.8,0.2" KeyTime="0:0:12"></LinearPointKeyFrame>
                        <LinearPointKeyFrame Value="0.7,0.3" KeyTime="0:0:14"></LinearPointKeyFrame>

                        <DiscretePointKeyFrame Value="0.7,0.3" KeyTime="0:0:20"></DiscretePointKeyFrame>
                        <DiscretePointKeyFrame Value="0.3,0.7" KeyTime="0:0:25"></DiscretePointKeyFrame>
                        <DiscretePointKeyFrame Value="0.5,0.9" KeyTime="0:0:28"></DiscretePointKeyFrame>
                        <DiscretePointKeyFrame Value="0.9,0.6" KeyTime="0:0:20"></DiscretePointKeyFrame>
                        <DiscretePointKeyFrame Value="0.8,0.2" KeyTime="0:0:22"></DiscretePointKeyFrame>
                        <DiscretePointKeyFrame Value="0.7,0.3" KeyTime="0:0:24"></DiscretePointKeyFrame>
                    </PointAnimationUsingKeyFrames>


                    <ColorAnimation Storyboard.TargetName="ellipse" Storyboard.TargetProperty="Fill.GradientStops[1].Color"
              To="Black"  Duration="0:0:10"
              AutoReverse="True" RepeatBehavior="Forever"></ColorAnimation>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Window.Triggers>
    <Grid>
        <Ellipse Name="ellipse" Margin="5" Grid.Row="1" Stretch="Uniform">
            <Ellipse.Fill>
                <RadialGradientBrush
             RadiusX="1" RadiusY="1" GradientOrigin="0.7,0.3">
                    <GradientStop Color="White" Offset="0" ></GradientStop>
                    <GradientStop Color="Blue" Offset="1" ></GradientStop>
                </RadialGradientBrush>

            </Ellipse.Fill>
        </Ellipse>
    </Grid>
</Window>

AnimateRadialGradient

经由过程修正LinearGradientBrush和RadialGradientBrush画刷的色彩和偏移值可建立很多出色结果。假如还不够,渐变画刷另有本身的RelativeTransform属性,可运用该属性扭转、缩放、拉伸以及歪曲画刷。WPF团队有一个风趣的称为Gradient Obsession的东西,该东西用于构建基于渐变的动画。

VisualBrush画刷

VisualBrush画刷可猎取恣意元素的表面,运用该表面可添补另一个外表。其他外表可所以任何内容,从广泛的矩形到文本框中的字母。

下图显现了一个基础示例。顶部是一个实在的运动按钮。下面经由过程VisualBrush画刷运用按钮图片添补一个矩形,并经由过程种种变更结果拉伸并扭转按钮图片。

【WPF学习】第五十三章 动画类型回首 IT教程 第13张

VisualBrush画刷还为完成一些风趣的动画结果的动画结果供应了大概。比方,不仅可动态显现运动的实在元素,还可动态显现具有雷同添补内容的简朴矩形。

为明白这类要领的事情道理,剖析这个示例,该例将一个元素放入试图中。当这个动画运行时,处置惩罚具有动画的元素的要领和处置惩罚其他恣意WPF元素的体式格局雷同,这意味着可单击它内部的按钮,或运用键盘转动内容(假如用户的操纵充足敏捷的话)。在一些状况下,这大概会令用户觉得疑心。在由写状况下,这大概致使机能下落,由于须要分外的开支来变更输入(如鼠标单击),而且和原始元素一同通报输入。

运用VisualBrush画刷可轻易地替代这类结果。起首,须要建立另一个元素,运用VisualBrush画刷添补该元素。VisualBrush画刷必需依据愿望包括动画的元素(在这个示例中,是名为visual的边框)绘制可视化内容。

<Rectangle Grid.Row="1" Name="rectangle" Width="100" Stretch="Uniform" ClipToBounds="False" RenderTransformOrigin="0.5,0.5">
            <Rectangle.Fill>
                <VisualBrush Visual="{Binding ElementName=visual}">

                </VisualBrush>
            </Rectangle.Fill>
            <Rectangle.RenderTransform>

                <TransformGroup>
                    <SkewTransform CenterX="0.5"></SkewTransform>
                    <RotateTransform CenterX="0.5" CenterY="0.5"></RotateTransform>
                </TransformGroup>

            </Rectangle.RenderTransform>
        </Rectangle>

示例完全XAML标记:

【WPF学习】第五十三章 动画类型回首 IT教程 第1张
【WPF学习】第五十三章 动画类型回首 IT教程 第2张

<Window x:Class="Animation.AnimateVisual"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="AnimateVisual" Height="300" Width="300" Background="LightGoldenrodYellow" WindowStartupLocation="CenterScreen">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <Button Name="visual" HorizontalAlignment="Center" VerticalAlignment="Center">
            <Button.Content>Test</Button.Content>
            <Button.Triggers>
                <EventTrigger RoutedEvent="Button.Click">
                    <BeginStoryboard>
                        <Storyboard  RepeatBehavior="Forever">
                            <DoubleAnimation Storyboard.TargetName="rectangle"
                                 Storyboard.TargetProperty="RenderTransform.Children[0].AngleY"
                                 To="180" Duration="0:0:15" AutoReverse="True"></DoubleAnimation>
                            <DoubleAnimation Storyboard.TargetName="rectangle"
                                 Storyboard.TargetProperty="RenderTransform.Children[1].Angle"
                                 To="180" Duration="0:0:20" AutoReverse="True"></DoubleAnimation>
                            <DoubleAnimation Storyboard.TargetName="rectangle"
                                 Storyboard.TargetProperty="Opacity"
                                 To="0.1" Duration="0:0:4" AutoReverse="True"></DoubleAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Button.Triggers>
        </Button>

        <Rectangle Grid.Row="1" Name="rectangle" Width="100" Stretch="Uniform" ClipToBounds="False" RenderTransformOrigin="0.5,0.5">
            <Rectangle.Fill>
                <VisualBrush Visual="{Binding ElementName=visual}">

                </VisualBrush>
            </Rectangle.Fill>
            <Rectangle.RenderTransform>

                <TransformGroup>
                    <SkewTransform CenterX="0.5"></SkewTransform>
                    <RotateTransform CenterX="0.5" CenterY="0.5"></RotateTransform>
                </TransformGroup>

            </Rectangle.RenderTransform>
        </Rectangle>
    </Grid>
</Window>

AnimateVisual

为将矩形放到与原始元素雷同的位置,可将它们同时放到Grid面板的同一个单元格中。转变单元格的尺寸,使其合适原始元素(边框),并拉伸矩形使其相匹配。另一个挑选是在实在有用程序上掩盖Canvas面板(然后可将动画属性绑定到下面实在元素的ActualWidth和ActualHeight属性,从而确保对齐)。

增添矩形后,只须要调解动画来实行动态变化。末了,当动画完成时隐蔽矩形:

private void storyboardCompleted(object sender,EventArgs e)
{
    rectangle.Visibility=Visibility.Collapsed;
}

三、动态转变像素着色器

经由过程“ ”的进修,相识了像素着色器(可为恣意元素运用位图作风结果的初级例程,如隐约、辉光以及蜿蜒结果)的相关内容。就本身而言,像素着色器是一些风趣而且偶然有效的东西。但经由过程连系运用动画,他们可变的更通用。可运用它们设想吸收眼球的过渡结果(比方,经由过程隐约控件使其淡出、隐蔽,然后隐约另一个控件使其淡入)。也可运用像素着色器建立给人留下深切印象的用户交互结果(比方,当用户将鼠标挪动到按钮上时增添按钮上的辉光)。末了为像素着色器的属性运用动画,就像为其他内容运用动画一样轻易。

下图显现的页面是基于在前面给出的扭转按钮示例构建的。该例包括一系列按钮,而且当用户将鼠标挪动到个中某个按钮上时,关联并入手下手动画。区分在于这个示例中的动画不是扭转按钮,而将隐约半径削减至0。结果是挪动鼠标时,近来的按钮蓦地轻快地变得清楚。

【WPF学习】第五十三章 动画类型回首 IT教程 第16张

该例的代码和扭转按钮示例中的代码雷同。须要为每一个按钮供应BlurEffect对象而不是RotateTransform对象:

<Setter Property="Effect">
     <Setter.Value>
            <BlurEffect Radius="10"></BlurEffect>
     </Setter.Value>
</Setter>

还须要响应地修正动画:

 <EventTrigger RoutedEvent="Button.MouseEnter">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="Effect.Radius"
         To="0" Duration="0:0:0.4"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>

                <EventTrigger RoutedEvent="Button.MouseLeave">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="Effect.Radius" To="10"
        Duration="0:0:0.2"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>

本实例完全XAML标记:

【WPF学习】第五十三章 动画类型回首 IT教程 第1张

<Window x:Class="Animation.BlurringButtons"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="BlurringButtons" Height="300" Width="300" WindowStartupLocation="CenterScreen">
    <Window.Resources>

        <Style TargetType="{x:Type Button}">
            <Setter Property="HorizontalAlignment" Value="Center"></Setter>
            <Setter Property="RenderTransformOrigin" Value="0.5,0.5"></Setter>
            <Setter Property="Padding" Value="20,15"></Setter>
            <Setter Property="Margin" Value="2"></Setter>
            <Setter Property="Effect">
                <Setter.Value>
                    <BlurEffect Radius="10"></BlurEffect>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <EventTrigger RoutedEvent="Button.MouseEnter">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="Effect.Radius"
         To="0" Duration="0:0:0.4"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>

                <EventTrigger RoutedEvent="Button.MouseLeave">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="Effect.Radius" To="10"
        Duration="0:0:0.2"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>

            </Style.Triggers>
        </Style>

    </Window.Resources>
    <StackPanel Margin="5">
        <Button>One</Button>
        <Button>Two</Button>
        <Button>Three</Button>
        <Button>Four</Button>
        <TextBlock Name="lbl" Margin="5"></TextBlock>
    </StackPanel>
</Window>

BlurringButtons

为反向运用雷同的要领来凸起显现按钮。比方,可运用运用辉光结果的像素着色器凸起显现鼠标在其上悬停的按钮。

使用Vagrant部署虚拟分布式开发和测试环境

参与评论