Marvin's Blog【程式人生】

Ability will never catch up with the demand for it

04 Mar 2021

UWP的Composition相关文档阅读

Visual layer

Visual layer为UI提供提供图形、效果和动画方面的支持。所有Windows设备的UI都具有Visual layer。UI是以声明的方式描述的,而Visual layer的工作就是把这些声明映射到底层的显示设备上。这些图形、效果和动画的实现跟App的UI进程无关。

Visual layer的实现要点:

  • 以WinRT方式提供API
  • 支持动态UI以及相关的交互
  • 采用的概念可以和设计工具适配
  • 可线性扩展,并且不会瞬时性能掉链子

Visual layer的层次在Framework layer(Windows.UI.Xaml)之下,但是在Graphics layer(也就是DirectX)之上。其主要功能包括

  • 内容:对自定义绘制的内容进行轻量级合成
  • 特效:支持实时UI效果,保证效果可以动画之,串联之以及自定义之。
  • 动画:具有表效力的,框架无关的动画,运行在UI线程之外。

内容的核心是Visual类型,一个轻量级的线程灵活的代理,驻留在应用进程之内,控制着compositor的状态。其派生类型包括ContainerVisual,以及SpriteVisual。

特效允许对Visual进行链式处理。

动画允许对Visual进行移动,对特效进行呈现,达成各种变换,、剪切的效果。

Windows.UI.Xaml.Hosting中的ElementCompositionPreview可以允许你获取XAML框架创建的Visual。你也可以自己创建一个Visual,然后附加到XAML中使用。

Visual layer同样也可以作用在WPF,Windows Forms,以及C++ Win32等制作的桌面程序。使用一个Island用于盛放Visual layer,将其与既有框架隔离开来。

Composition visual

Composition Visuals构建了一课可视化树。这是一种数据结果,为其他操作提供基础。所以相关的API主要用于构建这颗树。

可视化树的节点主要包括节点,以及应用于节点之上的画刷:

  • Visual,节点的基本数据类型
    • ContainerVisual,从Visual派生,用于作为树的枝干节点
      • SpriteVisual,带画刷,可以用来渲染像素,比如图片,特效,或者就是单色
      • LayerVisual,其子节点会被压缩成一个图层,1607 Win10引入
      • ShapeVisual,作为CompositionShape的根节点,1803 Win10引入
      • RedirectVisual,可以从其他Visual获取内容,1809 Win10引入
      • SceneVisual,用于3D scene,1903 Win10引入

SpriteVisual的内容和特效可以通过CompositionBrush以及其子类来应用。参照CompositionBrush Overview

下面是一个CompositionVisual的例子,展示了以下概念:

  • 创建一个合成器 Compositor
  • 创建一个SpriteVisual,以及CompositionColorBrush
  • 剪切Visual
  • 旋转Visual
  • 设置透明度
  • 改变Visual在列集中的位置

例子中的代码继承的接口是IFrameworkView以及IFrameworkViewSource。

Composition animations

Windows.UI.Composition API允许在App的UI线程之外运行60FPS的动画。主要就是通过CompositionAnimations。

在UI使用动画,可以通过XAML或者直接在Visual Layer进行。在后者上施行有以下优势:

  • 性能,可以脱离UI线程
  • 模板化,利用模板参数的调整来应对不同的场景
  • 自定义,支持更多动画类型

可以对CompositionObject的辖属或者子通道进行动画化。

不是所有的CompositionObject的辖属都可以被动画化。子通道指的是组件形式的辖属,比如Vector3的Offset辖属的X或者XY通道。

Time-based motion with KeyFrameAnimations

UI变化的时候,要么立即,要么渐进。 Windows比较青睐渐进式的UI变化,这样可以更好帮助用户理解。因此,Windows支持基于时间线的动画,也叫KeyFrameAnimations。

基于时间线的动画可以分为两类:显式的,用户触发的;以及隐式的,系统触发的。

根据所涉及的CompositionObjects的辖属的不同,又可以分为以下类型:

  • ColorKeyFrameAnimation
  • QuaternionKeyFrameAnimation
  • ScalarKeyFrameAnimation
  • Vector2KeyFrameAnimation
  • Vector3KeyFrameAnimation
  • Vector4KeyFrameAnimation

使用KeyFrameAnimations首先要了解以下概念:

  • KeyFrames,简单说就是动画的每一帧。定义成一个键值对。键是从0到1范围内的一个值。
  • KeyFrameAnimation辖属,可以在动画过程中用于UI自定义的一些辖属,包括
    • DelayTime,相对于StartAnimation的延迟
    • Duration,动画时长
    • IterationBehavior,如何重复
    • IterationCount ,重复次数
    • KeyFrame 个数
    • StopBehavior,StopAnimation 调用时的行为
    • Direction ,方向
  • Animation Group,动画群组,参考CompositionAnimationGroup

下面是构建一个KeyFrameAnimation的大概过程

  • 明确CompositionObject以及相关的辖属
  • 为compositor创建一个KeyFrameAnimation类型的动画模板,映射到需要应用动画的辖属
  • 在模板中添加KeyFrames,并定义动画相关的辖属
    • 最少需要一个KeyFrame
    • 最好页定义一个时长。
  • 调用CompositionObject的StartAnimation来启动动画,如下所示
    • visual.StartAnimation(“targetProperty”, CompositionAnimation animation);
    • visual.StartAnimationGroup(AnimationGroup animationGroup);
  • 停止的话,需要使用
    • visual.StopAnimation(“targetProperty”);
    • visual.StopAnimationGroup(AnimationGroup AnimationGroup);

一个例子:在1秒内采用10格动画,把一个元素从<0,0,0>移到<200,0,0>。 用Vector3KeyFrameAnimation 表示就是:

Vector3KeyFrameAnimation animation = compositor.CreateVector3KeyFrameAnimation();
    animation.InsertKeyFrame(1f, new Vector3(200f, 0f, 0f));

然后定义时长:

animation.Duration = TimeSpan.FromSeconds(2);
    animation.Direction = Windows.UI.Composition.AnimationDirection.Alternate;
    // Run animation for 10 times
    animation.IterationCount = 10;

下面的代码开始动画:

redVisual.StartAnimation("Offset", animation);

[Relation based animations]

不是的所有的motion都可以基于时间线。有些motion依赖于其他对象的辖属。这种情况下KeyFrameAnimations无法使用,而需要通过更加动态的手段。一个例子:在不同的水平位置为一个对象赋予不同的透明度。其他例子:粘性头部区域,以及Parallax。

基于关系的motion需要ExpressionAnimation的支持。它可以嵌入一个数学表达式,在每个帧进行计算,从而得出新的值。适用于下列场景:

  • Relative Size, Offset动画。
  • Sticky Headers, Parallax with ScrollViewer
  • Snap Points with InertiaModifiers and InteractionTracker.

ExpressionAnimation的使用有一些注意事项:

  • 可以停止,但不需要终止。不像KeyFrameAnimation那样具有时长的概念。
  • 持续运行,但是按需变化。只有输入参数发生变化的时候才需要重新计算。

https://docs.microsoft.com/en-us/windows/uwp/composition/relation-animations#using-expressionanimations

(未完待续)

Categories