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

如何仅用XAML实现汉堡菜单过渡动画(无代码后置)

纯XAML实现汉堡菜单切换动画

没问题!完全可以摆脱代码后置实现这个需求,核心思路就是用ToggleButton的IsChecked状态作为开关,配合触发器自动切换对应的动画故事板,不用手动维护状态变量。下面是完整的可运行方案:

完整XAML代码

<Window x:Class="HamburgerMenuDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="汉堡菜单" Height="450" Width="800">
    <Window.Resources>
        <!-- 打开菜单的动画(复用你原有的逻辑) -->
        <Storyboard x:Key="OpenMenu">
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="rectangle">
                <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="43.5"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="rectangle1">
                <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="-43.5"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="rectangle2">
                <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="GridMenu">
                <EasingDoubleKeyFrame KeyTime="0" Value="70"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="200"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
        <!-- 关闭菜单的动画(复用你原有的逻辑) -->
        <Storyboard x:Key="CloseMenu">
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="rectangle">
                <EasingDoubleKeyFrame KeyTime="0" Value="43.5"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="rectangle1">
                <EasingDoubleKeyFrame KeyTime="0" Value="-43.5"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="rectangle2">
                <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="GridMenu">
                <EasingDoubleKeyFrame KeyTime="0" Value="200"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="70"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>

        <!-- 自定义汉堡按钮样式,绑定状态触发动画 -->
        <Style x:Key="HamburgerButtonStyle" TargetType="ToggleButton">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ToggleButton">
                        <Grid Width="40" Height="40" Background="Transparent">
                            <!-- 汉堡菜单的三条横线 -->
                            <Rectangle x:Name="rectangle" Fill="Black" Width="25" Height="3" VerticalAlignment="Top" Margin="0,8,0,0">
                                <Rectangle.RenderTransform>
                                    <TransformGroup>
                                        <ScaleTransform/>
                                        <SkewTransform/>
                                        <RotateTransform/>
                                        <TranslateTransform/>
                                    </TransformGroup>
                                </Rectangle.RenderTransform>
                            </Rectangle>
                            <Rectangle x:Name="rectangle1" Fill="Black" Width="25" Height="3" VerticalAlignment="Bottom" Margin="0,0,0,8">
                                <Rectangle.RenderTransform>
                                    <TransformGroup>
                                        <ScaleTransform/>
                                        <SkewTransform/>
                                        <RotateTransform/>
                                        <TranslateTransform/>
                                    </TransformGroup>
                                </Rectangle.RenderTransform>
                            </Rectangle>
                            <Rectangle x:Name="rectangle2" Fill="Black" Width="25" Height="3" VerticalAlignment="Center"/>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <!-- 按钮选中时(打开菜单),执行OpenMenu动画 -->
                            <Trigger Property="IsChecked" Value="True">
                                <Trigger.EnterActions>
                                    <BeginStoryboard Storyboard="{StaticResource OpenMenu}"/>
                                </Trigger.EnterActions>
                                <!-- 按钮取消选中时(关闭菜单),执行CloseMenu动画 -->
                                <Trigger.ExitActions>
                                    <BeginStoryboard Storyboard="{StaticResource CloseMenu}"/>
                                </Trigger.ExitActions>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>

    <Grid>
        <!-- 菜单容器 -->
        <Grid x:Name="GridMenu" Width="70" Background="#FF2C3E50" VerticalAlignment="Stretch">
            <!-- 汉堡按钮 -->
            <ToggleButton Style="{StaticResource HamburgerButtonStyle}" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,10,0,0"/>
            <!-- 这里可以添加你的菜单内容 -->
        </Grid>
        <!-- 主内容区域 -->
        <Grid Margin="70,0,0,0" Background="#ECF0F1">
            <!-- 主内容放置在这里 -->
        </Grid>
    </Grid>
</Window>

核心逻辑解释

  1. 用ToggleButton代替普通Button:ToggleButton自带IsChecked属性,天生适合这种“开关”场景,不用自己维护StateClosed变量。
  2. 触发器绑定状态:
    • 当IsChecked变为True(第一次点击打开菜单),通过Trigger.EnterActions启动OpenMenu故事板
    • 当IsChecked变为False(再次点击关闭菜单),通过Trigger.ExitActions启动CloseMenu故事板
  3. 完全复用原有动画:你之前写的两个Storyboard可以直接复用,不需要修改任何关键帧参数,完美保留原来的动画效果。

这样就实现了完全无代码后置的汉堡菜单切换,所有交互逻辑都在XAML中完成~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 21:39:04