WPF製作視窗的啟動和關閉動畫

來源:互聯網
上載者:User

以下是用WPF實現的的一個視窗,為了使示範變得簡單,我在視窗中只放了一個按鈕。如所示:

 

但我們今天的主題是視窗啟動時和關閉時都展示動畫,如何進行動畫處理,我以前寫過一些WPF相關的文章。

要將視窗進行自訂,首先我們要去掉預設視窗的邊框、背景色和標題列。

這個不難,在WPF中,要把表單徹底透明,只要做三件事即可:

(1)設定WindowStyle屬性為None。

(2)AllowsTransparency屬性設定為true。

(3)Background屬性為Transparent。

為了使表單易於控制項,可以考慮設定ResizeMode="NoResize"。

 

視窗變成了透明,這使得視窗的整個地區就需要我們自己來設計了。

為了使自訂的視窗也有邊框,在最外層,我們應該考慮使用Border,然后里面放一個Grid,這個Grid劃分為兩行,第一行作為標題列,第二行作為視窗的用戶端區域。

    <Border x:Name="wb" CornerRadius="5" BorderThickness="3" BorderBrush="#FF1A55AA">        <Border.Background>            <LinearGradientBrush EndPoint="0.8,1" StartPoint="0.33,0">                <GradientStop Color="#FF50B3E2" Offset="0"/>                <GradientStop Color="#FF084168" Offset="1"/>            </LinearGradientBrush>        </Border.Background>        <Grid x:Name="root" >            <Grid.RowDefinitions>                <RowDefinition Height="auto"/>                <RowDefinition Height="*"/>            </Grid.RowDefinitions>            ……        </Grid>    </Border>

以上是視窗的大致架構。

接下來就是對最外層的Border進行剪裁,即設定它的Clip屬性。

    <Border x:Name="wb" CornerRadius="5" BorderThickness="3" BorderBrush="#FF1A55AA">        <Border.Background>            <LinearGradientBrush EndPoint="0.8,1" StartPoint="0.33,0">                <GradientStop Color="#FF50B3E2" Offset="0"/>                <GradientStop Color="#FF084168" Offset="1"/>            </LinearGradientBrush>        </Border.Background>        <Border.Clip>            <GeometryGroup FillRule="Nonzero">                <RectangleGeometry x:Name="r1" Rect="0,50,1000,100"/>                <RectangleGeometry x:Name="r2" Rect="0,220,1000,100"/>                <RectangleGeometry x:Name="r3" Rect="50,0,90,1000"/>                <RectangleGeometry x:Name="r4" Rect="360,0,160,1000"/>            </GeometryGroup>        </Border.Clip>        <Grid x:Name="root" >            <Grid.RowDefinitions>                <RowDefinition Height="auto"/>                <RowDefinition Height="*"/>            </Grid.RowDefinitions>            ……        </Grid>    </Border>

那麼,通過這四個矩形的裁剪,視窗會變成什麼模樣呢。看。

下面就是視窗的啟動動畫,通過對這四個矩形進行動畫處理,在表單的Loaded事件中播放動畫,當動畫播放完成時,再把這些Clip去掉,即設為null。

    <Window.Resources>        <Storyboard x:Key="start">            <RectAnimation Storyboard.TargetName="r1" Storyboard.TargetProperty="Rect"                           Duration="0:0:6" To="0,0,900,900"/>            <RectAnimation Storyboard.TargetName="r2" Storyboard.TargetProperty="Rect"                           Duration="0:0:5" To="20,20,700,800"/>            <RectAnimation Storyboard.TargetName="r3" Storyboard.TargetProperty="Rect"                           Duration="0:0:6" To="85,0,850,700"/>            <RectAnimation Storyboard.TargetName="r4" Storyboard.TargetProperty="Rect"                           Duration="0:0:6" To="0,250,800,700"/>            <DoubleAnimation Storyboard.TargetName="wb" Storyboard.TargetProperty="Opacity"                             From="0.2" To="1" Duration="0:0:6"/>        </Storyboard>        <Storyboard x:Key="end">            <DoubleAnimation Storyboard.TargetName="wb" Storyboard.TargetProperty="Opacity"                             Duration="0:0:5" From="1" To="0"/>            <DoubleAnimation Storyboard.TargetName="rt" Storyboard.TargetProperty="Angle"                             Duration="0:0:5" From="0" To="720"/>            <DoubleAnimation Storyboard.TargetName="sct" Storyboard.TargetProperty="ScaleX"                             Duration="0:0:5" From="1" To="0.3"/>            <DoubleAnimation Storyboard.TargetName="sct" Storyboard.TargetProperty="ScaleY"                             Duration="0:0:5" From="1" To="0.1"/>        </Storyboard>    </Window.Resources>

上面的資源中,包含兩個動畫,後面一個是視窗關閉時的動畫。

另外,我們的視窗還需要兩個小按鈕,就是標題列上方的“最小化”和“關閉”按鈕,用Button即可,不過我們要為Button類自訂一下控制項範本。

    <Application.Resources>        <Style TargetType="{x:Type Button}" x:Key="captionButtonStyle">            <Setter Property="Template">                <Setter.Value>                    <ControlTemplate  TargetType="{x:Type Button}">                        <Grid>                            <VisualStateManager.VisualStateGroups>                                <VisualStateGroup x:Name="CommonStates">                                    <VisualState x:Name="Normal"/>                                    <VisualState x:Name="MouseOver">                                        <Storyboard>                                            <DoubleAnimation Storyboard.TargetName="lbd"                                                             Storyboard.TargetProperty="Opacity"                                                             Duration="0:0:0.3"                                                             To="1"/>                                        </Storyboard>                                    </VisualState>                                    <VisualState x:Name="Pressed">                                        <Storyboard>                                            <DoubleAnimation Storyboard.TargetName="lbd"                                                             Storyboard.TargetProperty="Opacity"                                                             Duration="0"                                                             To="1"/>                                        </Storyboard>                                    </VisualState>                                    <VisualState x:Name="Disabled">                                        <Storyboard>                                            <DoubleAnimation Storyboard.TargetName="rctdisable"                                                             Storyboard.TargetProperty="Opacity"                                                             Duration="0" To="0.45"/>                                        </Storyboard>                                    </VisualState>                                </VisualStateGroup>                                <VisualStateGroup x:Name="FocusStates">                                    <VisualState x:Name="Focused"/>                                </VisualStateGroup>                                <VisualStateGroup x:Name="ValidationStates">                                    <VisualState x:Name="InvalidFocused"/>                                    <VisualState x:Name="InvalidUnfocused"/>                                </VisualStateGroup>                            </VisualStateManager.VisualStateGroups>                            <Border x:Name="lbd" BorderThickness="0" Background="{TemplateBinding Background}" CornerRadius="2" Opacity="0"/>                            <ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="{TemplateBinding Padding}" />                            <Rectangle x:Name="rctdisable" Opacity="0" Fill="#FFF4F8F9"/>                        </Grid>                    </ControlTemplate>                </Setter.Value>            </Setter>            <Setter Property="FontFamily" Value="Segoe UI Symbol"/>            <Setter Property="FontSize" Value="14"/>            <Setter Property="Foreground" Value="White"/>            <Setter Property="Padding" Value="3"/>        </Style>        <Style x:Key="minCaptionButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource captionButtonStyle}">            <Setter Property="Content" Value=""/>            <Setter Property="Background">                <Setter.Value>                    <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">                        <GradientStop Color="#BFFFFFFF"/>                        <GradientStop Offset="1"/>                    </LinearGradientBrush>                </Setter.Value>            </Setter>        </Style>        <Style x:Key="closeCaptionButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource captionButtonStyle}">            <Setter Property="Content" Value=""/>            <Setter Property="Background">                <Setter.Value>                    <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">                        <GradientStop Color="#FFEA1E1E" Offset="0"/>                        <GradientStop Color="#CCF5544C" Offset="0.7"/>                        <GradientStop Offset="1" Color="#33F94949"/>                    </LinearGradientBrush>                </Setter.Value>            </Setter>        </Style>    </Application.Resources>

由於這些小按鈕都比較相似,因此,我們先定義一個通用的樣式captionButtonStyle,而後的minCaptionButtonStyle和closeCaptionButtonStyle都是基於這個樣式的。

注意按鈕的字型要使用Segoe UI Symbol,這樣我們可以通過編號來引用一些特殊符號,如關閉按鈕上的 X 。

 

下面我們回到主表單,現在我把整個代碼貼出來。

<Window x:Class="WpfApplication2.MainWindow"        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        Title="主視窗" Height="400" Width="600"         ResizeMode="NoResize" WindowStartupLocation="CenterScreen"        WindowStyle="None" AllowsTransparency="True" Background="Transparent"        RenderTransformOrigin="0.5,0.5">        <Border x:Name="wb" CornerRadius="5" BorderThickness="3" BorderBrush="#FF1A55AA">        <Border.Background>            <LinearGradientBrush EndPoint="0.8,1" StartPoint="0.33,0">                <GradientStop Color="#FF50B3E2" Offset="0"/>                <GradientStop Color="#FF084168" Offset="1"/>            </LinearGradientBrush>        </Border.Background>        <Border.Clip>            <GeometryGroup FillRule="Nonzero">                <RectangleGeometry x:Name="r1" Rect="0,50,1000,100"/>                <RectangleGeometry x:Name="r2" Rect="0,220,1000,100"/>                <RectangleGeometry x:Name="r3" Rect="50,0,90,1000"/>                <RectangleGeometry x:Name="r4" Rect="360,0,160,1000"/>            </GeometryGroup>        </Border.Clip>        <Grid x:Name="root" >            <Grid.RowDefinitions>                <RowDefinition Height="auto"/>                <RowDefinition Height="*"/>            </Grid.RowDefinitions>            <Border x:Name="captiobd" Grid.Row="0" Background="#FF1A55AA" Height="32" MouseLeftButtonDown="onLDown">                <Grid>                    <TextBlock Text="{Binding Path=Title,RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType=Window}}"                               Foreground="White" FontWeight="Bold" FontSize="18" FontFamily="宋體"                               HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="9,0,0,5"/>                    <StackPanel Orientation="Horizontal" VerticalAlignment="Bottom" HorizontalAlignment="Right"                                Margin="0,0,9,11">                        <Button Style="{DynamicResource minCaptionButtonStyle}" Click="onMin" ToolTip="最小化"/>                        <Button Margin="6,0,0,0" Style="{DynamicResource closeCaptionButtonStyle}" Click="onClick" ToolTip="關閉"/>                    </StackPanel>                </Grid>            </Border>            <Button Content="關閉" Grid.Row="1" Click="onClick" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="30" Padding="15"  />        </Grid>    </Border>    <Window.RenderTransform>        <TransformGroup>            <RotateTransform x:Name="rt" Angle="0"/>            <ScaleTransform x:Name="sct" ScaleX="1" ScaleY="1"/>        </TransformGroup>    </Window.RenderTransform>    <Window.Resources>        <Storyboard x:Key="start">            <RectAnimation Storyboard.TargetName="r1" Storyboard.TargetProperty="Rect"                           Duration="0:0:6" To="0,0,900,900"/>            <RectAnimation Storyboard.TargetName="r2" Storyboard.TargetProperty="Rect"                           Duration="0:0:5" To="20,20,700,800"/>            <RectAnimation Storyboard.TargetName="r3" Storyboard.TargetProperty="Rect"                           Duration="0:0:6" To="85,0,850,700"/>            <RectAnimation Storyboard.TargetName="r4" Storyboard.TargetProperty="Rect"                           Duration="0:0:6" To="0,250,800,700"/>            <DoubleAnimation Storyboard.TargetName="wb" Storyboard.TargetProperty="Opacity"                             From="0.2" To="1" Duration="0:0:6"/>        </Storyboard>        <Storyboard x:Key="end">            <DoubleAnimation Storyboard.TargetName="wb" Storyboard.TargetProperty="Opacity"                             Duration="0:0:5" From="1" To="0"/>            <DoubleAnimation Storyboard.TargetName="rt" Storyboard.TargetProperty="Angle"                             Duration="0:0:5" From="0" To="720"/>            <DoubleAnimation Storyboard.TargetName="sct" Storyboard.TargetProperty="ScaleX"                             Duration="0:0:5" From="1" To="0.3"/>            <DoubleAnimation Storyboard.TargetName="sct" Storyboard.TargetProperty="ScaleY"                             Duration="0:0:5" From="1" To="0.1"/>        </Storyboard>    </Window.Resources></Window>

在X按鈕點擊時,我們不是直接Close視窗,因為我們還要關閉動畫,所以,單擊X按鈕時播放關閉動畫,當動畫結束時,才把視窗真正關掉。

    public partial class MainWindow : Window    {        Storyboard stdStart, stdEnd;        public MainWindow()        {            InitializeComponent();            stdStart = (Storyboard)this.Resources["start"];            stdEnd = (Storyboard)this.Resources["end"];            stdStart.Completed += (a, b) =>            {                this.root.Clip = null;            };            stdEnd.Completed += (c, d) =>                {                    this.Close();                };            this.Loaded += MainWindow_Loaded;        }        void MainWindow_Loaded(object sender, RoutedEventArgs e)        {            stdStart.Begin();        }        private void onClick(object sender, RoutedEventArgs e)        {            stdEnd.Begin();        }        private void onLDown(object sender, MouseButtonEventArgs e)        {            this.DragMove();            e.Handled = true;        }        private void onMin(object sender, RoutedEventArgs e)        {            this.WindowState = System.Windows.WindowState.Minimized;        }    }

好的,現在來看看這個視窗動畫吧。

是視窗啟動時的動畫。

 

是表單關閉時的動畫。表單一邊旋轉,一邊縮小,一邊淡出,直到消失。

原始碼我隨後上傳到資源區。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.