c# UWP 中的滑动元素
Sliding elements in c# UWP
我对 UWP 中的动画有疑问。我想在我的应用程序底部有一个菜单,当点击顶部时,它会向上滑动(显示)或向下滑动(几乎完全隐藏)。我之前学习过 WPF,我知道我可以使用 ThicknessAnimation 来移动控件的边距并让它滑动。不幸的是,在 UWP 中我不能使用 ThicknessAnimations,所以我试图找到另一种方法。我希望它适用于任意 FrameworkElement(以便能够重用它)。最终,我想出了这个解决方案:
/// <summary>
/// Adds a vertical slide animation
/// </summary>
/// <param name="storyboard">The storyboard to add the animation to</param>
/// <param name="seconds">The time the animation will take</param>
/// <param name="offset">The distance the element will cover (nagative is up, positive is down)</param>
public static void AddVerticalSlide(this Storyboard storyboard, FrameworkElement element, float seconds, double offset)
{
var slideAnimation = new ObjectAnimationUsingKeyFrames();
for (int i = 0; i <= 100; ++i)
{
double scalar = (double)i / 100;
slideAnimation.KeyFrames.Add(new DiscreteObjectKeyFrame
{
Value = new Thickness(0, scalar*offset, 0, -scalar*offset),
KeyTime = TimeSpan.FromSeconds(scalar*seconds),
});
}
//slideAnimation.Duration = TimeSpan.FromSeconds(seconds);
// Set the target and target property
Storyboard.SetTarget(slideAnimation, element);
Storyboard.SetTargetProperty(slideAnimation, "(FrameworkElement.Margin)");
// Add the animation to the storyboard
storyboard.Children.Add(slideAnimation);
}
它有效,看起来不错,但这就是我问这个问题的原因:我不知道它是否合适。我的猜测是,有一种比在途中手动定义 100 个点并使用此动画将对象移动到每个点更好的方法来滑动对象。
这可行,但不是 偏移 元素的理想方式。为什么?因为当您实际上只需要 一个 DoubleAnimation
.
时,您正在创建两个 DiscreteObjectKeyFrame
您几乎不应该为元素的 Margin
设置动画。要更改其位置,更好的方法是为其变换 (RenderTransform
) 的平移值 (即 TranslateX
/TranslateY
) 设置动画。
动画转换中的任何东西都是有效的。他们离开了 UI 话题。传统上,它们 运行 在一个名为 Compositor 线程的特殊线程中(我认为),但自从 Creators Update 以来,它们已经根据 Windows UI team -
变得更加高效
When you use Storyboard and Transition animations in XAML, you’re
using Composition under the hood. Animations run at 60 frames per
second!
下面是使用这种技术的例子
public static void Slide(this UIElement target, Orientation orientation, double? from, double to, int duration = 400, 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 = orientation == Orientation.Horizontal ? "X" : "Y";
Storyboard.SetTargetProperty(db, $"(UIElement.RenderTransform).(CompositeTransform.Translate{axis})");
var sb = new Storyboard
{
BeginTime = TimeSpan.FromMilliseconds(startTime)
};
sb.Children.Add(db);
sb.Begin();
}
请注意,随着这种方法的性能提高,UWP 中的动画支持更加强大,这要归功于新的合成 API。但是Composition中的偏移动画可以有点tricky。
但是,UWP Community Tookit 在包装一些有用的动画方面做得很好,例如 Blur
、Offset
等。欢迎查看 them出.
我对 UWP 中的动画有疑问。我想在我的应用程序底部有一个菜单,当点击顶部时,它会向上滑动(显示)或向下滑动(几乎完全隐藏)。我之前学习过 WPF,我知道我可以使用 ThicknessAnimation 来移动控件的边距并让它滑动。不幸的是,在 UWP 中我不能使用 ThicknessAnimations,所以我试图找到另一种方法。我希望它适用于任意 FrameworkElement(以便能够重用它)。最终,我想出了这个解决方案:
/// <summary>
/// Adds a vertical slide animation
/// </summary>
/// <param name="storyboard">The storyboard to add the animation to</param>
/// <param name="seconds">The time the animation will take</param>
/// <param name="offset">The distance the element will cover (nagative is up, positive is down)</param>
public static void AddVerticalSlide(this Storyboard storyboard, FrameworkElement element, float seconds, double offset)
{
var slideAnimation = new ObjectAnimationUsingKeyFrames();
for (int i = 0; i <= 100; ++i)
{
double scalar = (double)i / 100;
slideAnimation.KeyFrames.Add(new DiscreteObjectKeyFrame
{
Value = new Thickness(0, scalar*offset, 0, -scalar*offset),
KeyTime = TimeSpan.FromSeconds(scalar*seconds),
});
}
//slideAnimation.Duration = TimeSpan.FromSeconds(seconds);
// Set the target and target property
Storyboard.SetTarget(slideAnimation, element);
Storyboard.SetTargetProperty(slideAnimation, "(FrameworkElement.Margin)");
// Add the animation to the storyboard
storyboard.Children.Add(slideAnimation);
}
它有效,看起来不错,但这就是我问这个问题的原因:我不知道它是否合适。我的猜测是,有一种比在途中手动定义 100 个点并使用此动画将对象移动到每个点更好的方法来滑动对象。
这可行,但不是 偏移 元素的理想方式。为什么?因为当您实际上只需要 一个 DoubleAnimation
.
DiscreteObjectKeyFrame
您几乎不应该为元素的 Margin
设置动画。要更改其位置,更好的方法是为其变换 (RenderTransform
) 的平移值 (即 TranslateX
/TranslateY
) 设置动画。
动画转换中的任何东西都是有效的。他们离开了 UI 话题。传统上,它们 运行 在一个名为 Compositor 线程的特殊线程中(我认为),但自从 Creators Update 以来,它们已经根据 Windows UI team -
变得更加高效When you use Storyboard and Transition animations in XAML, you’re using Composition under the hood. Animations run at 60 frames per second!
下面是使用这种技术的例子
public static void Slide(this UIElement target, Orientation orientation, double? from, double to, int duration = 400, 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 = orientation == Orientation.Horizontal ? "X" : "Y";
Storyboard.SetTargetProperty(db, $"(UIElement.RenderTransform).(CompositeTransform.Translate{axis})");
var sb = new Storyboard
{
BeginTime = TimeSpan.FromMilliseconds(startTime)
};
sb.Children.Add(db);
sb.Begin();
}
请注意,随着这种方法的性能提高,UWP 中的动画支持更加强大,这要归功于新的合成 API。但是Composition中的偏移动画可以有点tricky。
但是,UWP Community Tookit 在包装一些有用的动画方面做得很好,例如 Blur
、Offset
等。欢迎查看 them出.