Search code examples
wpfanimationtriggersrendertransform

Stop Animation without resetting to start position wpf


I have the following in a style for a button, which is used for a refresh button - when the user hovers the mouse over the button, the image on it (in this case a circular arrow) spins around:

<Style x:Key="RefreshButton" TargetType="Button">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Grid Name="buttonContent">
                    <Image Source="/View/Images/Retry Green2.png" x:Name="Picture" RenderTransformOrigin="0.5,0.5">
                        <Image.RenderTransform>
                            <RotateTransform x:Name="AnimatedRotateTransform" Angle="0" />
                        </Image.RenderTransform>
                        <Image.Triggers>
                            <EventTrigger RoutedEvent="MouseEnter">
                                <BeginStoryboard Name="Spinner">
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetName="AnimatedRotateTransform"
                                                         Storyboard.TargetProperty="Angle" 
                                                         From="0" To="360" Duration="0:0:1"
                                                         RepeatBehavior="Forever"
                                             />
                                    </Storyboard>
                                </BeginStoryboard>
                            </EventTrigger>
                            <EventTrigger RoutedEvent="MouseLeave">
                                <StopStoryboard BeginStoryboardName="Spinner"/>
                            </EventTrigger>
                        </Image.Triggers>
                    </Image>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsPressed" Value="True">
                        <Setter Property="RenderTransform" TargetName="buttonContent">
                            <Setter.Value>
                                <TranslateTransform X="0" Y="2"/>
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

When the user moves their mouse away from the button, it stops spinning, which is good, but it also reverts to its original position at zero rotation (the same happens when the user clicks the button). Is there any way, within the style, to change the behaviour so that it stops spinning and remains at its new rotation orientation, both when the user moves the mouse away or when they click the button and it transforms down two points in the second RenderTransform?

The animation should pick up where it left off if the user mouse-overs the button another time.

I know it's a really small thing, but it is a niggle that won't go away and each time I use this template I have another stab at solving the problem without success. I can't help but think I am missing something. I am not helped by the fact that all the related problems I find are to do with animations not stopping at all - narrowing down the searches has proved very difficult.


Solution

  • I believe you are looking for this:

    https://learn.microsoft.com/en-us/dotnet/api/system.windows.media.animation.doubleanimation.isadditive?view=net-5.0

    To add to your DoubleAnimation.

    EDIT: This coupled with replacing StopStoryBoard with PauseStoryBoard should solve the problem. The final xaml should look like this in the Image.Triggers node:

    <Image.Triggers>
        <EventTrigger RoutedEvent="MouseEnter">
            <BeginStoryboard Name="Spinner">
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="AnimatedRotateTransform"
                                        Storyboard.TargetProperty="Angle"
                                        IsAdditive="true"
                                        From="0" To="360" Duration="0:0:1"
                                        RepeatBehavior="Forever"
                            />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
        <EventTrigger RoutedEvent="MouseLeave">
            <PauseStoryboard BeginStoryboardName="Spinner"/>
        </EventTrigger>
    </Image.Triggers>