2011-04-15 86 views
7

首先,我將嘗試解釋我正在嘗試做什麼。這個任務看起來很簡單,但是花了我一些時間才意識到它非常複雜。我想要做的是在開始時和結束時使用簡單的動畫 - 我知道如何使用緩動,最難的部分是我正在嘗試做一些類似於Orbit的橢圓軌道 - 讓我們說5個長方形到它。我想要沿着橢圓軌道(橢圓路徑)移動矩形而不改變每個矩形的旋轉角度。軌道動畫

我試過用路徑動畫,但似乎運動路徑動畫不支持緩動?我錯了嗎 ? 第二種解決方案是對路徑和矩形進行分組並旋轉整個組,但這也改變了矩形的旋轉角度。 有沒有簡單的方法來做到這一點?請指點我的文章或其他內容,或者如果您有類似的情況,請分享解決方案。謝謝。

回答

4

這裏的另一種方法......

你想要做什麼是不實際的旋轉,而是沿着橢圓形路徑的轉換。問題是,一個TranslateTransform由X和Y定義,而不是角度和半徑......但是更容易爲角度設置動畫,因此您必須將極座標轉換爲笛卡爾座標。

要做到這一點,讓我們定義兩個轉換器:SinConverterCosConverter

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 
} 

現在,我們需要的角度屬性動畫:所以我們定義的資源的虛擬RotateTransform,那將是目標動畫。

接下來,我們在「衛星」上應用TranslateTransform,我們使用我們的轉換器將X和Y綁定到角度。

最後,我們只需要創建動畫本身,這將動畫角度。

下面是完整的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

它也通過X&Y動畫,很好的完成這個任務。 – 2011-04-15 20:38:44

+0

謝謝托馬斯,這是我一直在尋找的答案。 – zlat 2011-04-18 12:00:22

11

試試這個,這是非常有趣:

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

要點:

  1. RotateTransformRenderTransform其上動畫的畫布。
  2. 通過Canvas.Resources的隱式樣式將矩形的RenderTransform綁定到父畫布的逆RotateTransform的
  3. ???
  4. 利潤!
+0

很聰明,我從來沒有注意到Transform類有逆財產......這是不是我的方法簡單,因爲你不需要我想過做任何代碼 – 2011-04-15 20:29:53