You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF中并行执行多动画实现窗口最小化效果的问题

窗口最小化并行动画实现方案

需求说明

需要实现窗口最小化时的同步动画效果:窗口同时进行360度旋转、视觉尺寸缩至0、透明度渐变为0,现有多动画并行方案无法满足需求。

当前问题

现有代码中两个独立的Storyboard以及Height/Width动画的布局延迟,导致动画顺序执行而非并行,无法达到预期同步效果。开发环境:.NET Framework 4.5 + WPF。

解决方案

修改思路

  1. 用TransformGroup整合旋转和缩放变换,避免窗口实际尺寸变化影响旋转中心,同时保证动画流畅性。
  2. 将所有动画合并到同一个Storyboard中,确保同步执行。
  3. 动画完成后再真正最小化窗口,并恢复窗口状态避免显示异常。

修改后的XAML代码

<Window x:Name="GanjAsemanMainWindow" x:Class="Ganj_Aseman.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Ganj_Aseman"
        mc:Ignorable="d"
        Loaded="GanjAsemanMainWindow_Loaded" 
        AllowsTransparency="True" 
        Background="Transparent" 
        FontSize="13" 
        Height="535" 
        ResizeMode="CanResizeWithGrip" 
        Title="MainWindow" 
        Width="764" 
        WindowStyle="None">
    <Window.RenderTransform>
        <TransformGroup>
            <RotateTransform x:Name="WindowRotateTransform" CenterX="382" CenterY="267.5"/>
            <ScaleTransform x:Name="WindowScaleTransform" CenterX="382" CenterY="267.5"/>
        </TransformGroup>
    </Window.RenderTransform>
    <Window.Resources>
        <Storyboard x:Key="MinimizeAnimation" Completed="MinimizeAnimation_Completed">
            <!-- 360度旋转动画 -->
            <DoubleAnimation Storyboard.TargetName="WindowRotateTransform"
                             Storyboard.TargetProperty="Angle"
                             From="0" To="360"
                             Duration="0:0:2"
                             SpeedRatio="0.9"/>
            <!-- 宽高同步缩放至0 -->
            <DoubleAnimation Storyboard.TargetName="WindowScaleTransform"
                             Storyboard.TargetProperty="ScaleX"
                             From="1" To="0"
                             Duration="0:0:2"
                             SpeedRatio="0.9"/>
            <DoubleAnimation Storyboard.TargetName="WindowScaleTransform"
                             Storyboard.TargetProperty="ScaleY"
                             From="1" To="0"
                             Duration="0:0:2"
                             SpeedRatio="0.9"/>
            <!-- 透明度渐变至0 -->
            <DoubleAnimation Storyboard.TargetName="GanjAsemanMainWindow"
                             Storyboard.TargetProperty="Opacity"
                             From="1" To="0"
                             Duration="0:0:2.5"
                             SpeedRatio="0.9"/>
        </Storyboard>
    </Window.Resources>
    <Grid>
        <Image x:Name="MinimizeIconImage" 
               PreviewMouseLeftButtonDown="MinimizeIconImage_PreviewMouseLeftButtonDown"
               MouseEnter="MinimizeIconImage_MouseEnter" 
               MouseLeave="MinimizeIconImage_MouseLeave" 
               GotFocus="MinimizeIconImage_GotFocus" 
               LostFocus="MinimizeIconImage_LostFocus" 
               Focusable="True" 
               FocusVisualStyle="{x:Null}" 
               Cursor="Hand" 
               Height="47"  
               VerticalAlignment="Top" 
               Source="{Binding}" 
               Margin="0,2,67,0" 
               HorizontalAlignment="Right" 
               Width="52"/>
    </Grid>
</Window>

修改后的C#代码

private void MinimizeIconImage_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    // 更新变换中心为窗口当前实际中心
    var centerX = ActualWidth / 2;
    var centerY = ActualHeight / 2;
    WindowRotateTransform.CenterX = centerX;
    WindowRotateTransform.CenterY = centerY;
    WindowScaleTransform.CenterX = centerX;
    WindowScaleTransform.CenterY = centerY;

    // 启动合并后的同步动画
    (Resources["MinimizeAnimation"] as Storyboard).Begin();
}

private void MinimizeAnimation_Completed(object sender, EventArgs e)
{
    // 动画结束后执行真正的最小化
    WindowState = WindowState.Minimized;
    // 恢复窗口状态,确保下次正常显示
    Opacity = 1;
    WindowScaleTransform.ScaleX = 1;
    WindowScaleTransform.ScaleY = 1;
    WindowRotateTransform.Angle = 0;
}

关键说明

  • 替换Height/Width动画为ScaleTransform:避免窗口实际尺寸变化引发的布局重算延迟,保证动画同步流畅。
  • 统一动画容器:所有动画放在同一个Storyboard中,默认同步启动,无需额外配置并行。
  • 动态更新变换中心:确保旋转和缩放始终围绕窗口视觉中心进行,避免窗口尺寸变化导致的偏移。
  • 动画完成后恢复状态:防止下次窗口显示时保留变换效果,保证正常交互。

内容的提问来源于stack exchange,提问作者Reza Jaferi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 17:18:18