Search code examples
animationexpression-blend

Moving an object relative to its current location in Expression Blend


I am new to Expression Blend 4 but am having a problem with something quite simple.

I would like a button to move an object up by 20px whenever the button is clicked. I followed a tutorial here that suggests if you use a storyboard animation (with no keyframe at the start) that moves the object then it will play the animation, moving it as planned from wherever the object currently is (ie: continue to move up each time pressed) however when I try this, the animation only works the once.

I have tried ticking the 'use relative values' box in the transform menu but it makes no difference.

Am I missing something obvious?


Solution

  • NOTE: the point values I'm referring to here are relative to the object's original location and not specific point values.

    I think the issue is that the Storyboard, while it has played all the way through, has not actually stopped. When you establish the end point of (-20,-20), that is relative to it's beginning point. Playing the animation again (assuming no keyframe at time zero) will move the object from it's existing location (-20,-20) to the target location which is also (-20,-20). This gives the appearance of no animation which is technically not accurate. If you had a separate animation with no keyframe at zero that moved the same object it would begin from wherever the object happens to be to the first keyframe in the animation.

    If you actually Stop the animation the object will return to it's original value at (0,0). Test this by adding a different Button that issues a Stop [I use the ControlStoryboardAction behavior for this]. Here is a sample you can use to test this:

    <UserControl 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:i="http://schemas.microsoft.com/expression/2010/interactivity"
             xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
             mc:Ignorable="d"
             x:Class="Animation1.MainPage"
             Width="640"
             Height="480">
    <UserControl.Resources>
        <Storyboard x:Name="Storyboard1">
            <DoubleAnimation Duration="0:0:0.8"
                             To="-20"
                             Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)"
                             Storyboard.TargetName="rectangle"
                             d:IsOptimized="True" />
            <DoubleAnimation Duration="0:0:0.8"
                             To="-20"
                             Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)"
                             Storyboard.TargetName="rectangle"
                             d:IsOptimized="True" />
        </Storyboard>
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot"
          Background="White">
        <Button Content="Play"
                HorizontalAlignment="Left"
                Height="37"
                Margin="35,53,0,0"
                VerticalAlignment="Top"
                Width="65">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <ei:ControlStoryboardAction Storyboard="{StaticResource Storyboard1}" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
        <Rectangle x:Name="rectangle"
                   Fill="#FF0303FF"
                   Height="99"
                   Margin="275,0,207,57"
                   Stroke="Black"
                   VerticalAlignment="Bottom"
                   RenderTransformOrigin="0.5,0.5">
            <Rectangle.RenderTransform>
                <CompositeTransform />
            </Rectangle.RenderTransform>
        </Rectangle>
        <Button Content="Stop"
                HorizontalAlignment="Left"
                Height="40"
                Margin="35,115,0,0"
                VerticalAlignment="Top"
                Width="65">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <ei:ControlStoryboardAction ControlStoryboardOption="Stop"
                                                Storyboard="{StaticResource Storyboard1}" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
    </Grid>
    

    I think you are going to have to approach this particular problem differently. The easiest would be to place this in a Canvas and manage the Top and Left values (preferably through a binding). The idea would be to capture the storyboard completion and update the values in the binding and then Stop the animation. This should give the correct starting point for the next time the animation is Played. Sorry I don't have time to put this together, but hopefully this will get you farther along.