anderZubi
anderZubi

Reputation: 6424

Rotate element in steps of 45 degrees, always forward

Let's say I want to animate rotate an UI element 45 degrees clockwise each time I press a button.

I have defined 8 visual states setting different RotateTransform values between them. So, whenever I press the button I move to the next visual state:

VisualStateManager.GoToElementState(MyElement, "Position2", True)

etc.

The problem is that when moving from the VisualState 8 to VisualState 1, the element rotates backward. Seems logical, since it is moving from 315º to 0º.

The question is, how could achieve to goal of always moving forward when pressing the button?

Upvotes: 0

Views: 1312

Answers (2)

rPulvi
rPulvi

Reputation: 946

I wrote a simple example for you in C#; VB should be very similar.

In your Main Window put a Rectangle and a Button. Then, set the RenderTransformOrigin for the Rectangle like in the Xaml sample.

In your code behind, declare your RotateTransform and attach it to the Rectangle as shown below. Everytime the Button is pressed, the Angle property of the RotateTransform is increased of 45.

@EDIT: I like @Clemens formula to increase angle (it avoid overflows). I edited my answer.

XAML:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <Rectangle x:Name="myRect" RenderTransformOrigin=".5,.5" Grid.Row="0" Width="100" Height="100" Fill="LightBlue" >

    </Rectangle>
    <Button Grid.Row="1" Width="100" Height="50" Margin="10" Click="Button_Click">Rotate</Button>
</Grid>

Window Code-Behind:

public partial class MainWindow : Window
{
    private TransformGroup _transformGroup;
    private RotateTransform _rotateTrsf;

    public MainWindow()
    {
        InitializeComponent();
        _transformGroup = new TransformGroup();
        _rotateTrsf = new RotateTransform();
        _transformGroup.Children.Add(_rotateTrsf);

        SetupAnimation();

        myRect.RenderTransform = _transformGroup;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        _rotateAnimation.To = Math.Floor(_rotateTrsf.Angle / 45 + 1) * 45;            
        _rotateTrsf.BeginAnimation(RotateTransform.AngleProperty, _rotateAnimation);
        _rotateAnimation.From = _rotateAnimation.To;            
    }

    private void SetupAnimation()
    {           
        _rotateAnimation = new DoubleAnimation();
        _rotateAnimation.From = 0.0;
        _rotateAnimation.To = 45;
        _rotateAnimation.Duration = new Duration(TimeSpan.FromSeconds(0.3));
    }
}

Upvotes: 1

Clemens
Clemens

Reputation: 128013

A basic example with animation could look like this:

<Grid>
    <Rectangle Fill="Black" Width="100" Height="100" RenderTransformOrigin=".5,.5">
        <Rectangle.RenderTransform>
            <RotateTransform x:Name="rotation"/>
        </Rectangle.RenderTransform>
    </Rectangle>
    <Button Content="Rotate" VerticalAlignment="Bottom" Click="Button_Click"/>
</Grid>

with this Button Click handler:

private void Button_Click(object sender, RoutedEventArgs e)
{
    const double rotSpeed = 180; // °/s, i.e. 45° in 0.25 seconds

    var newAngle = Math.Floor(rotation.Angle / 45 + 1) * 45; // integer multiple of 45°
    var duration = TimeSpan.FromSeconds((newAngle - rotation.Angle) / rotSpeed);

    rotation.BeginAnimation(
        RotateTransform.AngleProperty, new DoubleAnimation(newAngle, duration));
}

Upvotes: 3

Related Questions