如何仅在 XAML 中制作汉堡包菜单过渡动画

How to make Hamburger Menu Transition Animation in XAML only

我只想在 XAML 中创建汉堡包菜单过渡动画。 我只找到了有关如何使用代码隐藏执行此操作的教程和示例。 但这是我想不惜一切代价避免的事情。

动画是这样的: Animation (no direct GIF possible at the moment)

One example I found

XAML:

<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>
</Window.Resources>

代码隐藏:

    private void ButtonMenu_Click(object sender, RoutedEventArgs e)
    {
        if(StateClosed)
        {
            Storyboard sb = this.FindResource("OpenMenu") as Storyboard;
            sb.Begin();
        }
        else
        {
            Storyboard sb = this.FindResource("CloseMenu") as Storyboard;
            sb.Begin();
        }

        StateClosed = !StateClosed;
    }

是否可以仅使用 XAML 获得相同的结果。 我不想要此动画的任何代码隐藏...

我知道如何为动画本身创建每个故事板。 但是同一个按钮必须执行两个不同的故事板, 取决于菜单的状态?

这里是一个使用 ToggleButton 的例子。由于 ToggleButton 内置了 Checked / Unchecked 事件,您可以将 EventTrigger 中的事件用于 运行 您的故事板。

<ToggleButton ... >
    <!-- Your menu icon XAML/rectangles go here -->
    <ToggleButton.Triggers>
        <EventTrigger RoutedEvent="ToggleButton.Checked">
            <EventTrigger.Actions>
                <BeginStoryboard Storyboard="{StaticResource OpenMenu}" />
            </EventTrigger.Actions>
        </EventTrigger>
        <EventTrigger RoutedEvent="ToggleButton.Unchecked">
            <EventTrigger.Actions>
                <BeginStoryboard Storyboard="{StaticResource CloseMenu}" />
            </EventTrigger.Actions>
        </EventTrigger>
    </ToggleButton.Triggers>
</ToggleButton>