【问题标题】:Orbital animation轨道动画
【发布时间】:2011-04-15 19:02:50
【问题描述】:

首先,我将尝试解释我要做什么。这个任务乍一看很简单,但我花了一些时间才意识到它非常复杂。我想要做的是简单的动画,在开始和结束时都有缓动 - 我知道如何使用缓动,困难的部分是我正在尝试做类似 Orbit - Elliptical orbit 之类的东西,可以说附加了 5 个矩形给它。我想沿着椭圆轨道(椭圆路径)移动矩形而不改变每个矩形的旋转角度。

我尝试过使用路径动画,但似乎运动路径动画不支持缓动?我错了吗 ? 第二种解决方案是将路径和矩形分组并旋转整个组,但这也会改变矩形的旋转角度。 有没有一种简单的方法可以做到这一点?请指出我的文章或其他内容,或者如果您有类似的情况,请分享解决方案。谢谢。

【问题讨论】:

    标签: wpf animation path geometry


    【解决方案1】:

    试试这个,很好玩:

    <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 绑定到父画布的inverse RotateTransform
    3. ???
    4. 利润!

    【讨论】:

    • 非常聪明,我从来没有注意到 Transform 类有一个 Inverse 属性......它比我的方法更简单,因为你不需要任何代码
    【解决方案2】:

    这是另一种方法...

    您想要做的实际上不是旋转,而是沿椭圆路径的平移。问题是,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>
    

    【讨论】:

    • 我也想过通过 X 和 Y 动画来实现它,以这种方式完成它做得很好。
    • 谢谢托马斯,这就是我一直在寻找的答案。
    猜你喜欢
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-15
    • 2013-04-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多