Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Orbital animation

first of all I'll try to explain what I'm trying to do. The task looks quite simple at first look, but it took me some time to realize its very complex. What I'm trying to do is simple animation with easing at the beginning and at the end - I know how to use easing, the hard part is that I'm trying to do something like Orbit - Elliptical orbit with lets say 5 rectangles attached to it. I want to move the rectangles along the Elliptical orbit (elliptical path) without changing the rotation angle of each rectangle.

I've tried with Path animation, but it seems that motion path animations don't support easing ? Am I wrong ? Second solution was to group the path and the rectangles and rotate the whole group, but this changes rectangles rotation angle too. Is there a simple way to do this ? Please point me to an article or something, or if you have a similar scenario please share the solution. Thanks.

like image 494
zlat Avatar asked Apr 15 '11 19:04

zlat


People also ask

What are the four types of orbital?

There are four basic types of orbitals: s, p, d, and f. An s orbital has a spherical shape and can hold two electrons.

Is 7d orbital possible?

There are five 7d orbitals. These are labelled 7dxy, 7dxz, 7dyz, 7dx2-y 2 and 7dz2. Four of these functions have the same shape but are aligned differently in space. The fifth function (7dz2) has a different shape.

What are 5 types of orbitals?

Named for their energy sublevels, there are four types of orbitals: s, p, d, and f. Each orbital type has a unique shape based on the energy of its electrons. The s orbital is a spherical shape. The p orbital is a dumbbell shape.

Does 3d orbital exist?

The 3d orbitals are quite compactly arranged around the nucleus. Introducing a second electron into a 3d orbital produces more repulsion than if the next electron went into the 4s orbital. There is not a very big gap between the energies of the 3d and 4s orbitals.


2 Answers

Try this, it's great fun:

<Canvas Height="100" Width="100" RenderTransformOrigin="0.5,0.5">
    <Canvas.Triggers>
        <EventTrigger RoutedEvent="Canvas.Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation From="0" To="360"
                                     RepeatBehavior="Forever"
                                     Duration="0:0:1"
                                     Storyboard.TargetProperty="RenderTransform.Angle">
                        <DoubleAnimation.EasingFunction>
                            <CubicEase EasingMode="EaseInOut"/>
                        </DoubleAnimation.EasingFunction>
                    </DoubleAnimation>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Canvas.Triggers>
    <Canvas.RenderTransform>
        <RotateTransform />
    </Canvas.RenderTransform>
    <Canvas.Resources>
        <Style TargetType="{x:Type Rectangle}">
            <Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
            <Setter Property="RenderTransform" Value="{Binding RenderTransform.Inverse, RelativeSource={RelativeSource AncestorType=Canvas}}"/>
        </Style>
    </Canvas.Resources>
    <Rectangle Fill="Red" Height="20" Width="20" Canvas.Left="40" Canvas.Top="0"/>
    <Rectangle Fill="Green" Height="20" Width="20" Canvas.Left="40" Canvas.Top="80"/>
</Canvas>

Key Points:

  1. RotateTransform as RenderTransform on the Canvas which is animated.
  2. Implicit style via Canvas.Resources binds the RenderTransform of Rectangles to the inverse RotateTransform of the parent canvas.
  3. ???
  4. Profit!
like image 126
H.B. Avatar answered Nov 16 '22 20:11

H.B.


Here's another approach...

What you want to do is not actually a rotation, but a translation along an elliptic path. The trouble is, a TranslateTransform is defined by an X and Y, not an angle and radius... But it's easier to animate an angle, so you have to convert polar coordinates to cartesian coordinates.

To do that, let's define two converters: SinConverter and CosConverter:

public class SinConverter : IValueConverter
{
    #region Implementation of IValueConverter

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        try
        {
            double angle = System.Convert.ToDouble(value);
            double angleRad = Math.PI * angle / 180;
            double radius = System.Convert.ToDouble(parameter);
            return radius * Math.Sin(angleRad);
        }
        catch
        {
            return Binding.DoNothing;
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    #endregion
}

public class CosConverter : IValueConverter
{
    #region Implementation of IValueConverter

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        try
        {
            double angle = System.Convert.ToDouble(value);
            double angleRad = Math.PI * angle / 180;
            double radius = System.Convert.ToDouble(parameter);
            return radius * Math.Cos(angleRad);
        }
        catch
        {
            return Binding.DoNothing;
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    #endregion
}

Now, we need an angle property to animate: so we define a dummy RotateTransform in the resources, that will be the target of the animation.

Next, we apply a TranslateTransform on the "satellite", and we bind the X and Y to the angle, using our converters.

Eventually, we just need to create the animation itself that will animate the angle.

Here's the complete XAML:

<Window x:Class="WpfCS.Orbit"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:my="clr-namespace:WpfCS"
        Title="Orbit"
        Height="300" Width="300">
    <Window.Resources>
        <my:SinConverter x:Key="sinConverter" />
        <my:CosConverter x:Key="cosConverter" />
        <RotateTransform x:Key="rotate" Angle="0" />
    </Window.Resources>
    <Grid>
        <Rectangle Width="30" Height="30" Fill="Blue">
            <Rectangle.RenderTransform>
                <TranslateTransform X="{Binding Path=Angle,
                                                Source={StaticResource rotate},
                                                Converter={StaticResource cosConverter},
                                                ConverterParameter=100}"
                                    Y="{Binding Path=Angle,
                                                Source={StaticResource rotate},
                                                Converter={StaticResource sinConverter},
                                                ConverterParameter=60}"/>
            </Rectangle.RenderTransform>
        </Rectangle>
        <Ellipse Width="5" Height="5" Fill="White" Stroke="Black" StrokeThickness="1" />
    </Grid>
    <Window.Style>
        <Style TargetType="Window">
            <Style.Triggers>
                <EventTrigger RoutedEvent="Loaded">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.Target="{StaticResource rotate}"
                                         Storyboard.TargetProperty="Angle"
                                         From="0" To="360" Duration="0:0:5"
                                         RepeatBehavior="Forever" />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
            </Style.Triggers>
        </Style>
    </Window.Style>
</Window>
like image 44
Thomas Levesque Avatar answered Nov 16 '22 19:11

Thomas Levesque