2011-04-15 14 views
7

Przede wszystkim postaram się wyjaśnić, co próbuję zrobić. Zadanie wygląda dość prosto na pierwszy rzut oka, ale zajęło mi trochę czasu, aby zrealizować jego bardzo złożony. Co staram się zrobić to prosta animacja ze złagodzeniem na początku i na końcu - wiem, jak używać wygładzania, najtrudniejszą rzeczą jest to, że próbuję zrobić coś takiego jak orbita - eliptyczna orbita z powiedzmy 5 dołączonych prostokątów do tego. Chcę przesunąć prostokąty wzdłuż eliptycznej orbity (ścieżka eliptyczna) bez zmiany kąta obrotu każdego prostokąta.Animacja orbitalna

Próbowałem z animacją ścieżki, ale wydaje się, że animacje ścieżki ruchu nie obsługują łagodzenia. Czy się mylę ? Drugim rozwiązaniem było pogrupowanie ścieżki i prostokątów oraz obrócenie całej grupy, ale to również zmienia kąt obrotu prostokąta. Czy istnieje prosty sposób na zrobienie tego? Proszę wskazać mi artykuł lub coś, lub jeśli masz podobny scenariusz, podziel się rozwiązaniem. Dzięki.

Odpowiedz

4

Oto inne podejście ...

Co chcesz zrobić nie jest w rzeczywistości obrót, ale tłumaczenie wzdłuż eliptycznej ścieżce. Kłopot w tym, że TranslateTransform jest zdefiniowany przez X i Y, a nie przez kąt i promień ... Ale łatwiej jest ożywić kąt, więc musisz zamienić współrzędne biegunowe na współrzędne kartezjańskie.

Aby to zrobić, niech zdefiniować dwa konwertery: SinConverter i 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 
} 

Teraz musimy właściwość kąt animować: tak definiujemy obojętne RotateTransform w zasobach, które będą celem animacja.

Następnie stosujemy TranslateTransform na "satelicie" i wiążemy X i Y pod kątem, używając naszych konwerterów.

W końcu, musimy stworzyć animację, która będzie animować kąt.

Oto pełna 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> 
+0

myślałem o zrobieniu to także dzięki animacjom X i Y, dobra robota w ten sposób. –

+0

Dzięki Thomas, oto odpowiedź, której szukałem. – zlat

11

Spróbuj tego, to świetna zabawa:

<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> 

Kluczowe punkty:

  1. RotateTransform jak RenderTransform na płótnie, które są animowane.
  2. Niejawny styl przez Canvas.Resources wiąże RenderTransform prostokątów z odwróconym rotacyjnym przekształceniem płótna nadrzędnego.
  3. ???
  4. Zysk!
+0

Bardzo mądry, nigdy nie zauważyłem klasa Transform miał własności odwrotnego ... To prostsze niż moje podejście, ponieważ nie trzeba żadnego kodu –