如何创建转动动画?

时间:2017-08-03 14:11:24

标签: c# xaml animation uwp

我想制作一个转动动画,以显示车辆在Junction转弯。此外,我想用c#(代码隐藏)来做,因为我的车辆是动态添加的。

已尝试解决方案:

我尝试使用TranslateTransform和RotateTransform,但我只能创建急转弯动画。我想创建一个平滑的转动动画。

当前输出:

enter image description here

示例代码

//Code to add car
private void Click1_Click(object sender, RoutedEventArgs e)
{
    var myCar = new Image()
    {
        Source = new BitmapImage(new Uri("ms-appx:///Assets/RedCar.png")),
        Width = 140,
        Height = 65,
        HorizontalAlignment = HorizontalAlignment.Left,
        VerticalAlignment = VerticalAlignment.Top,
        RenderTransform = new TranslateTransform()
        {
            X = 0,
            Y = actualHeight / 2 - 145
        }
    };
    VehicleGrid.Children.Add(myCar);
}

//Code to create forward animation
private void MoreForward(UIElement element)
{
    Storyboard storyboard = new Storyboard();

    DoubleAnimation doubleAnimation = new DoubleAnimation()
    {
        Duration = new Duration(new TimeSpan(0, 0, 3)),
        To = LeftRoad.ActualWidth - 140
    };

    Storyboard.SetTarget(doubleAnimation, element.RenderTransform);
    Storyboard.SetTargetProperty(doubleAnimation, "X");
    storyboard.Children.Add(doubleAnimation);

    storyboard.Begin();
}

完整代码

您可以在Github中看到我的完整代码:TrafficManagementSystem

1 个答案:

答案 0 :(得分:2)

有一个有趣的post详细介绍了如何创建对象可以随之移动的布局路径。

但在像你这样的简单场景中,你基本上只想要一个曲线动作,就像this Android&#39> 材料设计指南中描述的一样 / em>的。是的...... Android,因为我们还没有原生的曲面运动API支持(Windows UI团队确实提到他们希望将来支持这一点)。

然而,创建自己的弯曲运动并不困难。事实上,许多人已经在网上使用过这个技巧 - 在每个轴上应用缓动相反速度。同样在你的情况下,你会希望缓和的曲线是锐利的,以产生一个很好的转动动画。

例如,对于从左到右然后左转的汽车,您可以在 x轴上应用QuinticEase EaseIn模式和一个 y轴上的EaseOut 。要转动车辆,只需对其应用另一个旋转动画,但延迟时间较短,持续时间较短,以确保仅在十字路口进行转弯。

通过稍微修改this question中的答案,您可以使用以下代码实现我上面描述的内容

AnimateTransform辅助方法

public static void AnimateTransform(this UIElement target, string propertyToAnimate, Orientation? orientation, double? from, double to, int duration = 3000, int startTime = 0, EasingFunctionBase easing = null)
{
    if (easing == null)
    {
        easing = new ExponentialEase();
    }

    var transform = target.RenderTransform as CompositeTransform;
    if (transform == null)
    {
        transform = new CompositeTransform();
        target.RenderTransform = transform;
    }
    target.RenderTransformOrigin = new Point(0.5, 0.5);

    var db = new DoubleAnimation
    {
        To = to,
        From = from,
        EasingFunction = easing,
        Duration = TimeSpan.FromMilliseconds(duration)
    };
    Storyboard.SetTarget(db, target);

    var axis = string.Empty;
    if (orientation.HasValue)
    {
        axis = orientation.Value == Orientation.Horizontal ? "X" : "Y";
    }
    Storyboard.SetTargetProperty(db, $"(UIElement.RenderTransform).(CompositeTransform.{propertyToAnimate}{axis})");

    var sb = new Storyboard
    {
        BeginTime = TimeSpan.FromMilliseconds(startTime)
    };

    sb.Children.Add(db);
    sb.Begin();
}

创建转动动画

MyCar.AnimateTransform("Translate", Orientation.Horizontal, null, -600, duration: 3000, easing: new QuinticEase
{
    EasingMode = EasingMode.EaseIn
});
MyCar.AnimateTransform("Translate", Orientation.Vertical, null, -600, duration: 3000, easing: new QuinticEase
{
    EasingMode = EasingMode.EaseOut
});
MyCar.AnimateTransform("Rotation", null, null, -90, duration: 2000, startTime: 500);

结果动作

enter image description here

或者,您可以使用新的 Composition API 替换传统的Storyboard动画,它提供完全可自定义的缓动函数(见下文),但想法是一样的。

public static CubicBezierEasingFunction EaseOutExpo(this Compositor compositor) =>
    compositor.CreateCubicBezierEasingFunction(new Vector2(0.14f, 1f), new Vector2(0.34f, 1f));

希望这有帮助!