视区和内容

直接操作 使用 视区内容联系人 来描述 UI 的交互式元素。

视区是窗口内的一个区域,可以接收和处理来自用户交互的输入。 视区表示在给定时间最终用户可以看到的内容区域, (也称为内容剪辑) 。 视区具有多个函数:

  • 它管理交互状态 (例如,当内容准备好被操作时、内容处于惯性动画) 并将输入映射到输出转换时。
  • 它包含为响应用户交互而移动的内容。 这可能是滚动) (HTML div 元素、 (Windows 8“开始”屏幕) 的平移列表或选择控件的弹出菜单。

通过调用 CreateViewport 创建视区。 可以在单个窗口中创建多个视区,以生成丰富的 UI 体验。

内容 表示为响应交互而转换的元素。 换句话说,内容是当用户平移或捏动时移动或缩放的内容。 有两种类型的内容:

  • 主要内容 是视区中响应输入操作和惯性的单一内部元素。 主内容与视区同时创建,不能在视区中添加或删除。 可以使用吸附点自定义主要内容的行为, (稍后) 讨论。
  • 次要内容 相对于主要内容的运动移动。 次要内容独立于视区创建,并且可以在视区中添加或删除。 所有次要内容转换都基于主要内容的转换进行计算。 可以应用特定规则来根据元素的预期用途更改转换的计算方式,该元素在创建期间由其 CLSID 标识。

在此显示平移之前和之后的图中,已使用单个触点平移主要内容。 即使用户没有直接与平移指示器 (辅助内容) 交互,辅助内容也会随着主要内容的平移而移动。 这提供了用户平移距离的视觉提示。

显示平移之前/之后的示意图

配置视区

创建视区后。 使用 交互配置来配置其行为。 交互配置指定支持哪些操作,如平移。

平移 将更改内容沿水平轴或纵坐标轴或同时沿两者的位置,因为用户平移。 在两个轴上配置翻译时,内容可自由地向任何方向移动。

若要限制内容的运动,请配置 导轨,通常同时在水平轴和垂直轴上。 如果用户的交互主要沿着单轴 (由下一个关系图) 中的蓝色区域表示,则平移将变为 有轨 ,内容仅沿着带栏的轴移动。 如果用户已平移并当前处于滑轨状态,并在内容处于惯性状态时执行第二次平移,则新平移将继续被围栏。

显示带栏平移中视区内内容的示意图

示例:视区配置为水平和垂直平移。 在第一帧中,触点下降。 第二种是启动垂直平移,触点锁定在垂直导轨上。 最后,一旦平移被围栏,仅使用对角平移的垂直组件来移动内容。

如果用户在对角线方向平移时不在导轨检测区域 () 的白色区域,则平移是 无轨的 ,内容将在两个轴上自由移动。

显示内容在无轨平移中移动的示意图

当用户 捏或拉伸时,缩放会更改内容的比例系数。 在 (缩放内容的点称为缩放中心) 位于触点的中心。 如果已设置水平或垂直对齐方式,则缩放中心将更改以保留对齐方式。

显示使用指定的对齐方式缩放内容的示意图

可以通过指定解锁中心来替代此行为,这将在联系人中心设置缩放中心。

显示缩放中心未锁定的内容缩放的示意图

惯性 是在触摸) 或键盘/鼠标输入 ((如单击滚动条或按箭头键) )的所有触点抬起 (之后,操作(平移和缩放)的逐渐减速。 当用户操作内容时,操作不会在解除联系人后立即停止。 相反,内容继续以当前方向和速度,逐渐减慢到停止。

吸附点和边界

在触摸 () 的情况下,由于手指被抬离屏幕,或者由于键盘/鼠标操作 ((如箭头键、页面向上/向下、鼠标滚轮滚动等) ),操作结束后,将发生惯性动画。

有两条定义惯性动画的信息:

  • 动画的其余点 – 特定转换组件的最终结束位置。
  • 动画持续时间、曲线、速度 - 这些由休息点的类型决定。

惯性动画受吸附点和边界的影响。 边界指定内容的最大和最小休息点。 如果内容在惯性期间到达边界,则将应用边界动画。 对齐点在主要内容上定义,用于修改休息点和修改惯性动画曲线本身。

当内容有固定间隔时,使用 SetSnapInterval 定义吸附点;如果内容不均匀,则使用 SetSnapInterval 定义吸附点。 下面是吸附点的示例:

显示内容中设置的对齐点如何影响平移的示意图

在图中,有一段内容包含一系列子内容块 - 新闻阅读器类型应用中的新闻项或网格视图中的项目。 目的是在惯性结束后将项的左边缘贴靠在视区左边缘上。

有两组吸附点类型:

  • 可选与必需:仅当惯性休息点靠近吸附点时,可选吸附点才会贴靠惯性动画。 强制吸附点始终将惯性动画贴靠到指定的吸附点。
  • 单个与多个:多对齐点类型允许内容在靠近其自然休息点的对齐点处经过多个对齐点之前移动。 单个吸附点类型选择下一个最近的吸附点作为惯性动画的休息点。

下图演示了吸附点类型如何修改惯性动画的其余位置。

显示惯性和吸附点如何交互的关系图

在此图中,惯性起点标记为“开始”,在没有吸附点的情况下,自然惯性结束位置标记为“结束”。 垂直线标记各种吸附点。 下表描述了每种类型的吸附点将如何影响动画的结束位置。

点类型 说明
必需单一 选择吸附点 P1,因为它是惯性方向上的第一个吸附点
必需多个 选择吸附点 P2 是因为它在惯性方向上最接近终点
可选单一 选择吸附点 P1,因为它是惯性期间遇到的第一个吸附点
可选多个 选择吸附点 P2 是因为它靠近自然终点

吸附点偏移和 RTL 方案

显示 rtl 对齐点使用情况的示意图

可使用 SetSnapCoordinate API 应用吸附点偏移量和坐标系,该 API 使用指定的偏移/坐标系来偏移所有对齐点或对齐间隔。

坐标系在 RTL 方案中非常有用,你希望从内容的左边缘向相反方向描述对齐点。 在上图中, SetSnapCoordinateDIRECTMANIPULATION_MOTION_TRANSLATEXDIRECTMANIPULATION_COORDINATE_MIRRORED 标志一起使用,该标志自动偏移内容左边缘的对齐点,并按从右到左的顺序提供它们:S1 为 0px,S2 为 50px (,依) 依此) 。 使用 SetSnapCoordinate 设置的任何偏移量将自动从内容的左边缘进一步偏移,包括正确的比例系数。

你几乎总是将 SetSnapCoordinate 参数集一起使用,以避免在内容区域之外设置吸附点。

例如,如果视区为 200x200,内容为 1000x200,并且接口为 RTL,则当首次显示视区时,视口的左边缘为 x=800。 使用 SetSnapCoordinate(DIRECTMANIPULATION_MOTION_TRANSLATEX, DIRECTMANIPULATION_COORDINATE_MIRRORED, 1000.0) 调用 SetSnapCoordinate 以指定应从内容右边缘开始按从右到左的顺序计算吸附点。

行为

行为是可以附加到视区的对象,以修改直接操作处理视区主内容或辅助内容的输出转换的方式。 行为对象可能会影响操作的一个或多个方面,例如处理输入的方式或惯性动画的应用方式。 例如,自动滚动行为通过向主要内容的一端执行滚动动画来影响惯性动画。 跨幻灯片配置行为会影响直接操作输入处理,后者会检测何时执行交叉幻灯片操作。

通过调用 CreateBehavior 创建行为对象,将其添加到视区,然后异步配置其行为。 从视区中删除行为会删除其效果。

坐标系统

直接操作采用三个main坐标系:

  • 客户端坐标系 - 描述客户端窗口的矩形。 单位以像素为单位。
  • 视区坐标系 - 描述客户端中可以处理输入的区域的矩形。 单元是使用 SetViewportRect) 应用程序定义的 (。
  • 内容坐标系统 - 描述主内容的矩形或大小。 单元是使用 SetContentRect) 的应用程序定义的 (。

对于所有这三个系统,坐标是相对于其各自的左上原点定义的,并且向右和向下呈正增长。 下一个关系图中演示了这些坐标系。 最终用户只能查看或操作视区矩形中的内容部分。

显示内容、客户端和视区坐标如何交互的关系图

转换

直接操作 维护多个不同的转换,这些转换有助于显示的整体输出。

  • 内容转换直接操作 基于操作或惯性计算的初始转换。 它捕获吸附点、栏杆、默认过跨 (操作) 、默认过度 (惯性) 和 ZoomToRect 动画的效果。
  • 输出转换 - 最终的视觉对象或输出转换。 它是内容和同步转换的组合。
  • 同步转换 - 在调用 SyncContentTransform 时计算。 它可帮助 直接操作 应用应用程序提供的新内容转换,同时维护现有的输出转换。
  • 显示转换 - 应用程序在后期处理过程中应用。 有关更多详细信息 ,请参阅 SyncDisplayTransform

由于输出转换旨在在屏幕上直观地偏移图面, 因此 Direct Manipulation 对输出转换组件执行必要的舍入,以便始终在整型像素边界上呈现/复合文本和其他内容。 舍入机制取决于多种因素,包括运动速度和远程桌面的存在。 次要内容的舍入机制与主要内容的舍入机制匹配,同时考虑到两者之间的运动差异。 GetOutputTransform 的客户端不应依赖于输出转换的确切舍入机制,因为各种因素会影响它。

注意

这意味着内容转换的组件可能不是整型,并且可能包含子像素偏移量。 建议使用 直接操作 的客户端在使用手动更新模式时使用 GetOutputTransform 来计算要应用于内容的正确视觉转换。 使用内置合成器使用自动更新模式时,直接操作会自动代表客户端应用此转换。 此转换由直接操作生成,以确保在撰写视觉输出时获得美观的结果。

视区状态

处理输入时,视区管理输入到输出转换的交互状态和映射。 通过调用 GetStatus 检查视区交互状态。

显示直接管理交互状态的示意图

  • 正在生成 - 正在创建视区,但尚无法处理输入。 若要处理输入,请调用 IDirectManipulationViewport::Enable。 如果未调用 Enable ,则视区将进入“已禁用”状态。

    注意

    这是交互的初始状态。

  • 已启用 – 视区已准备好处理输入。 当触点 (SetContact 被调用) 并检测到操作时,视区将转换为“正在运行”。

  • 正在运行 - 视区当前正在处理输入和更新内容。 抬起触点时,视区将转换为惯性(如果已配置)。

  • 惯性 – 内容在惯性动画中移动。 惯性完成后,视区将转换为就绪。 如果在视区上设置了自动禁用,它将从惯性转换为就绪,然后转换为“已禁用”。

  • 就绪 - 视区已准备好处理输入。 当触点 (SetContact 被调用) 并检测到操作时,视区将转换为“正在运行”。

  • 已暂停 – 当视区输入提升为 SetContact 链中的父级时,视区可能会变为“挂起”。 这在多个视区中进行了更详细的讨论 :命中测试和视区层次结构

  • 已禁用 – 视区不会处理输入或进行回调。 可以通过调用 IDirectManipulationViewport::D isable 从各种状态禁用视区。 如果在视区上设置了自动禁用,则处理操作后,它将自动转换为“已禁用”。 若要重新启用已禁用的视区,请调用 IDirectManipulationViewport::Enable

多个视区:命中测试和视区层次结构ActivateConfigurationGetOutputTransformSyncDisplayTransform