AnimationExample综合动画实例

clipboard.png

功能说明:

  1. 主界面显示各页动画缩略按钮,点击后加载对应页的动画,按钮界面隐藏
  2. 主界面显示页动画,并有退出按钮实现返回到前者。
  3. 各页动画实现

文件组织:
clipboard.png

具体设计、实现说明:
主窗口界面设计:
1、界面缩略选择按钮为自定义RadioButton.一个特定是选中后不能再点击选中,私认为还是使用自定义Button更适合。另外示例未设置好Tab按钮,在播放动画时,背后使用Tab选择另一页动画替换播放。

  1. 内容为Frame,直接设置Source,直接在小框里显示了,这性能。。。
<RadioButton Grid.Column="2" Grid.Row="0" Style="{StaticResource GlassRadioButtonStyle}">

      <Frame 
        Name="SkewTextAnimationExampleFrame"
        Source="text\SkewTextAnimationExample.xaml"
        NavigationUIVisibility="Visible" />

    </RadioButton>

2、RadioButton的玻璃效果,细节不解释了,看代码:

<Style TargetType="{x:Type RadioButton}" x:Key="GlassRadioButtonStyle">

<Setter Property="Margin" Value="1" />
<Setter Property="Background">
    <Setter.Value>

        <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
            <LinearGradientBrush.GradientStops>
                <GradientStop Offset="0.0" Color="#CCCCFF" />
                <GradientStop Offset="1.0" Color="DarkGray" />
            </LinearGradientBrush.GradientStops>
        </LinearGradientBrush>

    </Setter.Value>
</Setter>

<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type RadioButton}">
            <Grid Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" 
  ClipToBounds="true">


                <Rectangle x:Name="outerRectangle" 
    HorizontalAlignment="Stretch" 
    VerticalAlignment="Stretch" 
    Stroke="{TemplateBinding Background}" 
    StrokeThickness="1" Fill="Transparent" />

                <Rectangle x:Name="glassCube" HorizontalAlignment="Stretch" 
    VerticalAlignment="Stretch"
    StrokeThickness="2" RadiusX="10" RadiusY="10" Opacity="0" 
    Fill="{StaticResource MyGlassBrushResource}"
    RenderTransformOrigin="0.5,0.5"
    >
                    <Rectangle.Stroke>
                        <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                            <LinearGradientBrush.GradientStops>
                                <GradientStop Offset="0.0" Color="LightBlue" />
                                <GradientStop Offset="1.0" Color="Gray" />
                            </LinearGradientBrush.GradientStops>
                        </LinearGradientBrush>
                    </Rectangle.Stroke>
                    <Rectangle.RenderTransform>
                        <TransformGroup>
                            <ScaleTransform x:Name="cubeScaleTransform" />
                            <RotateTransform x:Name="cubeRotateTransform" />
                        </TransformGroup>
                    </Rectangle.RenderTransform>
                </Rectangle>


                <DockPanel Margin="10">

                    <Viewbox Stretch="Uniform">
                        <ContentPresenter x:Name="myContentPresenter"  
        Content="{TemplateBinding  Content}" 
        TextBlock.Foreground="Black" />
                    </Viewbox>

                </DockPanel>
                <Rectangle Fill="Transparent" />
            </Grid>


            <ControlTemplate.Triggers>
                <MultiTrigger>
                    <MultiTrigger.Conditions>
                        <Condition Property="IsMouseOver" Value="true" />
                        <Condition Property="IsChecked" Value="false" />
                    </MultiTrigger.Conditions>
                    <Setter Property ="Rectangle.Stroke" Value="Black" TargetName="outerRectangle" />
                    <Setter Property="Rectangle.Opacity" Value="1" TargetName="glassCube" />
                </MultiTrigger>
                <Trigger Property="IsChecked" Value="true">
                    <Setter Property="Rectangle.Opacity" Value="1" TargetName="glassCube" />
                </Trigger>
                <Trigger Property="IsFocused" Value="true">
                    <Setter Property="Rectangle.Stroke" Value="Black" TargetName="outerRectangle" />
                    <Setter Property="Rectangle.Opacity" Value="1" TargetName="glassCube" />
                </Trigger>
                <EventTrigger RoutedEvent="Mouse.MouseEnter">
                    <EventTrigger.Actions>
                        <BeginStoryboard Name="mouseEnterBeginStoryboard">
                            <Storyboard>
                                <DoubleAnimation
            Storyboard.TargetName="cubeScaleTransform"
            Storyboard.TargetProperty="ScaleX"
            By="-0.1" Duration="0:0:0.5" />
                                <DoubleAnimation
            Storyboard.TargetName="cubeScaleTransform"
            Storyboard.TargetProperty="ScaleY"
            By="-0.1" Duration="0:0:0.5" />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
                <EventTrigger RoutedEvent="Mouse.MouseLeave">
                    <EventTrigger.Actions>
                        <StopStoryboard BeginStoryboardName="mouseEnterBeginStoryboard" />
                    </EventTrigger.Actions>
                </EventTrigger>
                <EventTrigger RoutedEvent="RadioButton.Checked">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation
            Storyboard.TargetName="cubeRotateTransform"
            Storyboard.TargetProperty="Angle"
            By="360" Duration="0:0:0.5" />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Setter.Value>
</Setter>
</Style>

3、主界面容器为Grid,除了包含一个上面的缩略按钮的Grid,还有个Border层:DockPanel容器右侧有一个退出按钮,左侧为主Frame区,平时Border.Visibility=“Collapsed”隐藏。

  1. 点击退出按钮触发:之前的Grid.Opacity=1动画显示出来,并且其移动变换的X,To=0执行动画.
  2. Border层的移动变换的X,To值绑定到窗口ActualWidth执行动画。(此处就有缺陷了,如下)此处的解决方法是在添加动画完成后事件,清除属性上的动画,重新设值。

clipboard.png
增加修改的代码,及加个动画是否完成的判断:

 private void xSampleDisplayBorderDoubleAnimation_Completed(object sender, EventArgs e)
{
    SampleDisplayBorderTranslateTransform.ApplyAnimationClock(TranslateTransform.XProperty, null);
    SampleDisplayBorderTranslateTransform.X = ActualWidth;
}

//判断动画已完成x=0状态,若>0,此时若动画未解除,以下的设置可以无效,一举两得。
private void PageSizeChanged(object sender, SizeChangedEventArgs args)
{
    if (SampleDisplayBorderTranslateTransform.X>0)
    {
        SampleDisplayBorderTranslateTransform.X = ActualWidth;
    }
}

主界面退出按钮Border层代码:

<Border Name="SampleDisplayBorder" BorderBrush="Gray" BorderThickness="1"
  Visibility="Collapsed"
  Background="Black">
  <DockPanel 
    Margin="10"  HorizontalAlignment="Stretch">


    <Button
      DockPanel.Dock="Right"
      Height="50" Width="50" Click="Button_Click">
      <Button.Triggers>
          
        <EventTrigger RoutedEvent="Button.Click">
          <BeginStoryboard HandoffBehavior="SnapshotAndReplace">
            <Storyboard>
                
              <DoubleAnimation
                Storyboard.TargetName="SampleGrid"
                Storyboard.TargetProperty="Opacity"
                From="0"
                To="1" BeginTime="0:0:0" />
                
              <DoubleAnimation
                Storyboard.TargetName="SampleGridTranslateTransform"
                Storyboard.TargetProperty="X"
                To="0" 
                BeginTime="0:0:0" />

            <DoubleAnimation Name="xSampleDisplayBorderDoubleAnimation"
                Storyboard.TargetName="SampleDisplayBorderTranslateTransform"
                Storyboard.TargetProperty="X"
                BeginTime="0:0:0"
                Duration="0:0:1"
                From="0"
                To="{Binding ElementName=SampleDisplayBorder, Path=ActualWidth,Mode=OneWay}"
                 Completed="xSampleDisplayBorderDoubleAnimation_Completed"/>                                                    

            </Storyboard>
          </BeginStoryboard>
        
        </EventTrigger>
      </Button.Triggers>
    </Button>


    <Frame Name="SampleDisplayFrame" Background="White" 
      ContentRendered="SampleDisplayFrameLoaded"
      NavigationUIVisibility="Hidden" >
                
    </Frame>


  </DockPanel> 
  <Border.RenderTransform>
    <TranslateTransform x:Name="SampleDisplayBorderTranslateTransform"
      X="0" />
  </Border.RenderTransform>
</Border> 

4、 RadioButton选中后切换页

  1. 确定RadioButton对应的Frame.Source,加载到主Frame中。
private void SelectedSampleChanged(object sender, RoutedEventArgs args)
{
    if (args.Source is RadioButton)
    {
        var theButton = (RadioButton) args.Source;
        var theFrame = (Frame) theButton.Content;

        if (theFrame.HasContent)
        {
            var source = theFrame.CurrentSource;
            if ((source != null) && !source.IsAbsoluteUri)
            {
                source = new Uri(PackUri, source);
            }
            SampleDisplayFrame.Source = source;

            //未报错,但会造成RadioButtond的内容不显示。
            //SampleDisplayFrame.Content= theFrame.Content;                    
        }
        
        //此处设置 为不管是否已加载Frame, 都显示此Border及退出按钮
        SampleDisplayBorder.Visibility = Visibility.Visible;
    }
}

在主Frame加载n内容执行对应的切换动画

private void SampleDisplayFrameLoaded(object sender, EventArgs args)
{
    SampleGrid.BeginAnimation(OpacityProperty, _sampleGridOpacityAnimation);
    SampleGridTranslateTransform.BeginAnimation(TranslateTransform.XProperty,
        _sampleGridTranslateTransformAnimation);
    SampleDisplayBorderTranslateTransform.BeginAnimation(TranslateTransform.XProperty,
        _borderTranslateDoubleAnimation);

    //可省略,加载Frame时已设置。
    //SampleDisplayBorder.Visibility = Visibility.Visible;
}

简单分析:以上的退出按钮代码的演示板动画可放在Xaml里设置,后台代码就只实现选择加载页、优化窗口改变事件、清除属性动画的功能代码即可。


李志玮
22 声望34 粉丝

求索~~


引用和评论

0 条评论