WPF中并行执行多动画实现窗口最小化效果的问题
窗口最小化并行动画实现方案
需求说明
需要实现窗口最小化时的同步动画效果:窗口同时进行360度旋转、视觉尺寸缩至0、透明度渐变为0,现有多动画并行方案无法满足需求。
当前问题
现有代码中两个独立的Storyboard以及Height/Width动画的布局延迟,导致动画顺序执行而非并行,无法达到预期同步效果。开发环境:.NET Framework 4.5 + WPF。
解决方案
修改思路
- 用
TransformGroup整合旋转和缩放变换,避免窗口实际尺寸变化影响旋转中心,同时保证动画流畅性。 - 将所有动画合并到同一个
Storyboard中,确保同步执行。 - 动画完成后再真正最小化窗口,并恢复窗口状态避免显示异常。
修改后的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
相关产品推荐
相关产品推荐

