本文介绍如何使用 XAML ScrollViewer 和 ExpressionAnimations 创建动态输入驱动的运动体验。
先决条件
此处,我们假设你熟悉以下文章中讨论的概念:
为什么在 ScrollViewer 的基础上生成?
通常,使用现有的 XAML ScrollViewer 为应用内容创建可滚动且可缩放的图面。 随着 Fluent Design 语言的引入,你现在还应该专注于如何使用滚动或缩放图面的行为来驱动其他运动体验。 例如,使用滚动来驱动背景的模糊动画或驱动“粘滞标头”的位置。
在这些情景中,你将利用像滚动和缩放这样的行为操作体验,使应用的其他部分更加动态。 这些反过来使得应用程序更具凝聚力,使得在最终用户眼中,体验更加令人难忘。 通过使应用界面更加令人难忘,用户将更频繁地与应用互动并且使用时间更长。
可以在 ScrollViewer 的基础上生成哪些内容?
可以利用 ScrollViewer 的位置来生成许多动态体验:
- 视差 – 使用 ScrollViewer 的位置将背景或前景内容以相对速率移动到滚动位置。
- StickyHeaders – 使用 ScrollViewer 的位置对标题进行动画处理,并将标题“粘附”到某个位置
- Input-Driven 效果 - 使用 Scrollviewer 的位置对合成效果(如 Blur)进行动画处理。
通过使用 ExpressionAnimation 引用 ScrollViewer 的位置,通常可以创建一个根据滚动量动态变化的动画。
具有视差效果的 
使用 ScrollViewerManipulationPropertySet
若要使用 XAML ScrollViewer 创建这些动态体验,必须能够引用动画中的滚动位置。 这是通过从名为 ScrollViewerManipulationPropertySet 的 XAML ScrollViewer 中访问 CompositionPropertySet 来完成的。 ScrollViewerManipulationPropertySet 包含一个名为 Translation 的 Vector3 属性,该属性提供对 ScrollViewer 滚动位置的访问权限。 在 ExpressionAnimation 中,可以像引用任何其他 CompositionPropertySet 一样引用它。
入门的常规步骤:
- 通过 ElementCompositionPreview 访问 ScrollViewerManipulationPropertySet。
ElementCompositionPreview.GetScrollViewerManipulationPropertySet(ScrollViewer scroller)
- 创建一个 ExpressionAnimation,该表达式引用 PropertySet 中的 Translation 属性。
- 不要忘记设置引用参数!
- 使用 ExpressionAnimation 来针对 CompositionObject 的属性。
注释
建议将 GetScrollViewerManipulationPropertySet 方法返回的 PropertySet 分配给类变量。 这可确保垃圾回收机制不会清理属性集合,因此它不会对其所引用的 ExpressionAnimation 产生任何影响。 ExpressionAnimations 不会对公式中使用的任何对象保持强引用。
示例:
让我们看看上面所示的视差样本是如何组合在一起的。 供参考,应用的所有源代码都位于 GitHub上的
第一件事是获取对 ScrollViewerManipulationPropertySet 的引用。
_scrollProperties =
ElementCompositionPreview.GetScrollViewerManipulationPropertySet(myScrollViewer);
下一步是创建 ExpressionAnimation,用于定义利用 ScrollViewer 滚动位置的公式。
_parallaxExpression = compositor.CreateExpressionAnimation();
_parallaxExpression.SetScalarParameter("StartOffset", 0.0f);
_parallaxExpression.SetScalarParameter("ParallaxValue", 0.5f);
_parallaxExpression.SetScalarParameter("ItemHeight", 0.0f);
_parallaxExpression.SetReferenceParameter("ScrollManipulation", _scrollProperties);
_parallaxExpression.Expression = "(ScrollManipulation.Translation.Y + StartOffset - (0.5 * ItemHeight)) * ParallaxValue - (ScrollManipulation.Translation.Y + StartOffset - (0.5 * ItemHeight))";
注释
还可以利用 ExpressionBuilder 帮助程序类来构造此相同的表达式,而无需字符串:
var scrollPropSet = _scrollProperties.GetSpecializedReference<ManipulationPropertySetReferenceNode>(); var parallaxValue = 0.5f; var parallax = (scrollPropSet.Translation.Y + startOffset); _parallaxExpression = parallax * parallaxValue - parallax;
最后,应用此 ExpressionAnimation 并将其针对需要视差效果的视觉对象。 在这种情况下,它是列表中每个项的图像。
Visual visual = ElementCompositionPreview.GetElementVisual(image);
visual.StartAnimation("Offset.Y", _parallaxExpression);