语言: HTML | XAML

在应用中使用动画 (HTML)

Applies to Windows and Windows Phone

在 JavaScript 应用中使用动画,享受与其他 Windows 应用相同的快速、流畅的用户体验。动画可为 UI 状态赋予过渡效果,使你感觉到你的应用对用户输入具有良好的响应性。动画可为用户提供有用的视觉提示,但又不会干扰应用的操作或分散对应用的注意力。

若要下载演示本主题中所讨论的诸多概念的示例,请参阅 HTML 动画库示例。本主题中的代码示例均选取自该示例。

路线图: 本主题与其他主题有何关联?请参阅:

动画资源

有些动画内置于 Windows 控件中。当你使用这些控件时,无需进一步编码,即可获得它们的动画。但是,你也可以选择使用动画库。在使用动画库时,你可以为应用创建自定义动画,同时又可以保留 Windows 设计的观感体验。

使用内置动画

有些动画是 Windows 的组成部分,会自动提供给你。

Windows 系统动画

系统提供的某些动画适用于所有应用窗口。应用不必执行任何显式操作即可获取这些系统动画。但是,有几个要点需要注意,如下所示。

应用启动

应用启动过程中涉及到两个动画。第一个动画演示了从在开始屏幕上选中应用到应用初始屏幕出现的应用启动阶段。第二个动画以交叉淡入淡出形式淡出初始屏幕,淡入应用的背景。建议你的应用在初始屏幕淡出后也使用自己的动画来显示第一页内容。

旋转和调整大小更改

当应用由于大小或方向更改而更新其布局时,系统动画可以使过渡具有平滑效果。

屏幕键盘的进入和退出

当应用中的某个文本输入控件成为焦点时,将自动显示屏幕键盘。默认情况下,必要时应用的内容将自动滚动,以使输入控件在屏幕上持续显示。你的应用不需要任何特别的操作。

Windows 控件和 HTML 控件

以下控件中包含动画。建议你尽可能使用这些控件。

此外,在使用常用 HTML 表单控件(例如按钮、复选框和下拉菜单)时,无需为类似于单击或悬停的用户操作提供响应动画。这些控件要么已经含有必需的动画,要么由于使用颜色变化或其他某种视觉指示形式向用户提供反馈,因而不需要动画。

所有这些元素的样式均通过 Microsoft Visual Studio 项目模板中的 WinJS CSS 和 UI.js 文件自动进行应用。

使用动画库

你可以通过使用动画库向应用添加自定义动画。动画库是一套动画,它体现了 Windows 和 Windows Phone 中动态图像设计的个性化。这些动画可供开发人员用于其应用中,通过构成 WinJS.UI.Animation 命名空间的函数便可以在应用中使用它们。有关动画库的详细信息,包括各个动画的相关视频和指南,请参阅创建 UI 动画

在以下情况下,你必须提供自己的动画:

  • 删除整个控件
  • 更改应用的内容
  • 在应用中浏览网页

通过动画库提供的所有动画均使用 CSS 动画和 CSS 过渡来实现。动画库动画可以为 CSS 的“暗度”和“转换”属性赋予动画效果。

使用动画库函数中的元素和偏移参数

很多动画库函数中包含相同的参数,这些参数的使用方法也相同。

元素

很多动画库函数用文档对象模型 (DOM) 元素作为动画目标。此参数可以用以下方式表达:

  • 作为特殊值“undefined”,表示动画没有此类目标
  • 作为单个对象
  • 作为元素的 JavaScript 数组(可能为空)。
  • 作为节点列表 (NodeList),例如 querySelectorAll 的结果
  • 作为 HTML 集合 (HTMLCollection)

偏移

offset 参数是包含转换的元素动画和过渡的一部分。这些动画要么将元素从偏移位置移动到最终位置,要么将其从当前位置移动到偏移位置。

一些动画具有推荐的偏移,你可以通过将 nullundefined 作为偏移参数进行传递或完全忽略该参数来使用这些偏移。你应该尽可能使用这些默认偏移,它们可带来以下益处:

  • 改善动画性能
  • 在从右向左的应用中实现自动镜像
  • 由设计师推荐的转换距离,它将在你的应用调整大小时自动进行调整(采用适用的动画)

除非在理由充分的设计例外情况下,否则这些动画均应始终使用默认偏移:

对于其他动画库动画,偏移可以视应用而定,需考虑到你的具体 UI。以下所有函数都具有默认偏移,如果未提供指定偏移,则会使用该偏移,但你通常会基于应用的设计指定偏移。

你可以采用多种形式提供 offset 参数:

  • 作为特殊值“undefined”,你可以在调用中显式指定该值,也可以通过忽略该参数值来隐式指定。undefined 值表示将使用动画的默认偏移。
  • 作为此表单的单个 JavaScript 对象:

    { top: string, left: string, rtlflip: true | false }

    例如:

    { top: "12px", left: "0px", rtlflip: true }

    该对象中必须具有命名为“top”和“left”的属性,这两个属性代表在动画开始应用的偏移。任何有效的 CSS 单位均可用来表达偏移。在此表单中,该偏移将应用于动画中涉及到的所有元素。

    rtlflip 参数将值翻转,以进行从右向左对齐。它影响“left”参数,并更改其符号。例如,10 px 变为 -10px。此参数为可选参数,可以忽略 。如果忽略此参数,则默认值为 false

  • 作为上述 {top: ..., left: ..., rtlflip: ...} 对象的 JavaScript 数组(可能为空)。在这种情况下,数组中的每个对象分别按指定顺序应用于动画中的单个元素;第一个对象应用于第一个元素,第二个对象应用于第二个元素,依此类推。如果元素的数量大于此数组中的对象数量,那么数组中的最后一个对象将应用于余出的所有元素。只有一个动画通常需要使用数组来记录多个偏移记录,这个动画是 dragBetweenEnter。对于其他动画,通常最好是只传递一个偏移记录,将其用于所有元素。

Promise 返回值

所有动画库动画的返回值均为一个 Promise 对象。此对象的 donethen 方法可以用于跟踪动画的完成时间。Promise 对象还提供一个 cancel 方法,你可以使用该方法来取消正在运行的动画。

动画类型

动画库中的动画分为三个类型:元素动画、元素过渡和布局过渡。每个类型均有不同的实现模式。

元素动画

元素动画以 CSS 动画的形式实现。元素动画不更改元素的状态;它们是在当前状态基础之上的动画。例如,showPanel 动画是一个元素动画,它从屏幕边缘滑动一个面板,如任务窗格。showPanel 动画将面板以动画方式从开发人员指定的偏移位置转换到该元素的当前位置。

若要使用元素动画,你需要设置元素的最终状态。在如下示例中,myPanel 元素已经处于显示前的最终位置,但是它当前不可见。为显示该面板,你的代码将面板元素的不透明度设置为 1,然后触发动画。只要上述步骤都发生在同一个函数中,不透明度更改就不会在动画开始前生效。面板显示在其偏移位置,然后以动画方式移动到其实际位置。



                                                
myPanel.style.opacity = "1";
WinJS.UI.Animation.showPanel(myPanel, { top: "0px", left: "350px" });                                       
                                            

若要隐藏该面板,进程顺序需反转。首先,你的代码必须调用 hidePanel,这时面板将以动画方式从其当前位置移动到偏移位置。动画完成后,你的代码将不透明度设置为 0,以隐藏该元素。如果你未在代码中包含不透明度更改,则元素在动画结束时将显示重新贴靠回其原始位置,并且在屏幕上依然可见。



                                                
WinJS.UI.Animation.hidePanel(myPanel, { top: "0px", left: "350px" })
    .then(function () { myPanel.style.opacity = "0"; });                                       
                                            

以下是动画库中的元素动画:

函数描述
showEdgeUI 将基于边缘的 UI 滑入视图。将目标元素以动画方式从偏移位置转换到当前位置。
hideEdgeUI 将基于边缘的 UI 滑出视图。将目标元素以动画方式从当前位置转换到偏移位置。
showPanel 将基于边缘的大型面板滑入视图。将目标元素以动画方式从偏移位置转换到当前位置。
hidePanel 将基于边缘的大型面板滑出视图。将目标元素以动画方式从当前位置转换到偏移位置。
showPopup 在视图顶部显示上下文 UI。将不透明度以动画方式变为 1,并以动画方式从偏移位置转换到当前位置。
hidePopup 隐藏上下文 UI。将不透明度以动画方式变为 1。
updateBadge 更新数字锁屏提醒。将不透明度以动画方式变为 1,并以动画方式从偏移位置转换到当前位置。

 

元素过渡

元素过渡以 CSS 过渡的形式实现。元素过渡通过将 CSS 属性过渡为动画定义的值来更改元素的状态。

动画库中的很多元素过渡均以成对动画形式存在,成对的动画应该结合使用。由成对动画中的一个动画应用的状态更改将由另一个动画进行反转。例如,fadeIn 动画将元素的不透明度过渡为 1,而 fadeOut 动画则将该元素的不透明度过渡为 0。

动画库中的某些动画会结合使用元素动画和元素过渡。例如,enterContent 动画将内容的不透明度过渡为 1,同时它还将内容以动画方式从偏移位置转换到当前位置。

以下是动画库中仅使用元素过渡的动画以及结合使用元素过渡和元素动画的动画:

函数描述
fadeIn 显示过渡元素或控件。将不透明度过渡为 1。
fadeOut 隐藏过渡元素或控件。将不透明度过渡为 0。
enterContent 将一条内容或一组内容以动画方式呈现到视图。将不透明度以动画方式过渡为 1,并以动画方式从偏移位置转换到当前位置。
exitContent 将一条内容或一组内容以动画方式呈现到视图。将不透明度过渡为 0。
enterPage 将完整的页面内容以动画方式呈现到视图。将不透明度以动画方式过渡为 1,并以动画方式从偏移位置转换到当前位置。
exitPage 将完整的页面内容以动画方式退出视图。将不透明度过渡为 0。
crossFade 刷新内容区域。在进入的内容上将不透明度过渡为 1,并在退出的内容上将不透明度过渡为 0。
pointerDown 当用户点击或单击磁贴时提供视觉反馈。将比例过渡为一个更小些的值。
pointerUp 当用户松开点击或单击磁贴的操作时提供视觉反馈。将比例还原为最大化。
dragSourceStart 当用户开始拖放操作时提供视觉反馈。将比例过渡为稍大些的值,并降低不透明度。此动画还将周边(受影响的)元素的比例过渡为稍小些的值。
dragSourceEnd 当用户通过放开拖动的对象来完成拖放操作时提供视觉反馈。反转 dragSourceStart 执行的动画。
dragBetweenEnter 提供视觉反馈,表明如果将拖动的对象放到该位置上,那么当前位于所拖动对象下方的元素将被移开。将受影响对象的转换属性过渡为偏移。
dragBetweenLeave 提供视觉反馈,表明通过反转 dragBetweenEnter 执行的动画,所拖动对象具有左拖放区域。
swipeSelect 将磁贴过渡到已选中轻扫的状态。将磁贴的不透明度过渡为 0,同时将“已选中”偏移的视觉对象的不透明度过渡为 1。
swipeDeselect 将磁贴过渡到已取消选中轻扫的状态。将“已选中”偏移的视觉对象的不透明度过渡为 0,同时将原始磁贴的不透明度过渡为 1。
swipeReveal 向用户提供视觉提示,表明磁贴支持轻扫交互。以过渡方式从当前位置转换到偏移位置。
turnstileBackwardIn 使元素顺时针旋转进入页面。
turnstileBackwardOut 使元素顺时针旋转离开页面。
turnstileForwardIn 使元素逆时针旋转进入页面。
turnstileForwardOut 使元素逆时针旋转离开页面。
slideDown 将元素滑过屏幕底部。
slideUp 将元素从屏幕底部向上滑动至视图。
slideLeftIn 将元素从屏幕左侧滑入。
slideLeftOut 将元素从屏幕左侧滑出。
slideRightIn 将元素从屏幕右侧滑入。
slideRightOut 将元素从屏幕右侧滑出。
continuumBackwardIn 在缩小进入的页面时,缩放、旋转和翻译传入的项目。
continuumBackwardOut 在删除页面时,缩放、旋转和翻译传出的页面。
continuumForwardIn 将项目引入屏幕,并在放大传入的页面时,缩放、旋转和翻译传入的项目。
continuumForwardOut 从屏幕删除项目,并在缩小传出的页面时,缩放、旋转和翻译传出的项目。

 

布局过渡

与元素动画和元素过渡相比,动画库中的布局过渡动画更为复杂。布局过渡动画通常涉及到多个元素,最终引起布局更改。但是,此类动画函数不能假设布局更改的实现方式。例如,在 reposition 动画中,元素从点 A 移动到点 B。这一过程可以有多种实现方式,例如更改元素的宽度、偏移、边距或填充。

对于布局过渡,动画库提供创建函数并返回一个带有 .execute() 方法的对象。用于这些动画的调用模式如下:

  1. 调用对应的创建动画函数。将收集目标元素的当前位置。
  2. 该应用将使用它选择的任意方式执行布局更改。
  3. 该应用将在创建函数返回的对象上调用 execute 方法以触发动画。这会收集目标元素的新位置,并使用动画将其从原始位置过渡到新位置。
  4. execute 方法将返回可用于普通方法的 Promise 对象。

下面的示例显示了添加到列表动画,该动画可用于将项目以动画方式插入到列表的顶部。当调用 createAddToListAnimation 时,将记录 affectedItems 集合中传递的所有元素的位置。此集合中包含新项目的抵达会影响到其位置的所有元素。

调用 createAddToListAnimation 后,示例在列表顶部插入了一个新项目。在下一个代码中,list 是包含列表项目的 div 元素。调用元素的 insertBefore 方法将执行把 newItem 实际添加到列表顶部的操作。此插入操作导致列表中的所有其他项目的位置发生更改。你可以视需要任意更改 affectedItems 集合的位置。

最后,此示例通过调用 createAddToListAnimation 返回的对象的 execute 方法触发了动画,从而将新的列表项目移动到相应位置。



                                                
var addToList = WinJS.UI.Animation.createAddToListAnimation(newItem, affectedItems);
list.insertBefore(newItem, list.firstChild);
addToList.execute();
                                            

以下是动画库中的布局过渡动画创建函数:

函数描述
createExpandAnimation 显示更多嵌入式信息。必要时移动其他内容,以让出位置。
createCollapseAnimation 隐藏内联内容。必要时折叠其他内容。
createRepositionAnimation 将元素移动到新位置。
createAddToListAnimation 在列表中添加一个项目。
createDeleteFromListAnimation 从列表中删除一个项目。
createAddToSearchListAnimation 向列表中添加一个项目,同时筛选搜索结果。
createDeleteFromSearchListAnimation 从列表中删除一个项目,同时筛选搜索结果。
createPeekAnimation 在磁贴上显示快速查看动画。快速查看磁贴会在磁贴空间内上下滚动以显示全部信息。

 

安排动画

若要完成一个复杂的方案,通常需要在 UI 的不同部分运行不同的动画。 例如,当你删除电子邮件时,你可能需要从列表中移除已删除的电子邮件,然后显示下一封电子邮件。在大多数情况下,最好同时运行这两个动画,以缩短整体用时。下部分内容将介绍在此类方案中应注意的问题。

中断动画

如果针对同一 CSS 属性的另一动画或过渡也被触发,则动画或过渡将被中断。根据 CSS3 规范,出现这种情况时将取消第一个动画或过渡。CSS 过渡之间的相互中断平滑而流畅。然而,在 CSS 动画中,它们显示的过渡在元素顶部带有 CSS 属性,同时元素中的实际 CSS 属性值保持不变。如果中断 CSS 动画,会突然跳回属性的原始值,不建议此操作。对于 CSS 动画,通常最好等待第一个动画结束后再开始下一个动画。有关详细信息,请参阅等待动画完成

方案结果
CSS 动画中断 CSS 动画正在进行动画处理的 CSS 属性还原到其“true”状态,然后开始新的动画。这会在视觉上造成不悦。
CSS 动画中断过渡无论过渡处于哪个点,都会平滑地中断该过渡,并开始以动画方式从当前值转换到新的结束值。
CSS 过渡中断过渡无论过渡处于哪个点,都会平滑地中断该过渡,并开始从当前值过渡到新的结束值。
CSS 过渡中断动画正在进行动画处理的 CSS 属性还原到其“true”状态,然后开始新的过渡。这会在视觉上造成不悦。

 

取消动画

通过使用动画函数返回的 Promise 对象的 cancel 方法,可以取消任何运行中的动画库动画。

等待动画完成

若要在动画完成时执行某个操作,请向动画函数返回的 Promise 对象的 donethen 方法传递回调函数。这在有些情况中会很有用,例如等待在退出动画完成后从 DOM 删除某个项目,或连续呈现多个动画。在如下所示的示例中,只有在目标完全淡入后,回调函数才开始将目标淡出。



                                                
WinJS.UI.Animation.fadeIn(target)
       .then(function () { WinJS.UI.Animation.fadeOut(target); });
                                            

建议不要使用 JavaScript 计时器来确定动画的完成时间。这样做并不可靠;计时器的完成时间可能会早于或晚于动画的完成时间,并且计时器的计时可能会由于硬件及 UI 线程上运行的其他进程的不同而有所不同。

启用和禁用动画

  • Applies to Windows

Windows:在系统设置中选择“禁用所有不必要的动画”后,将禁用所有动画库动画,该设置位于控制面板中“使计算机更易于查看”下的“轻松使用”项内。选择此设置后,不是应用的基本功能所必需的所有动画均将关闭。在游戏应用中,这通常意味着除玩游戏所必需的一些游戏动画之外的所有动画。使用 executeAnimationexecuteTransition 的动画库动画和自定义动画会自动响应此设置。如果你创建自定义动画,你的代码必需显式受此设置约束。

作为开发人员,你可以决定在你的应用中使用的动画库动画是否响应 WinJS.UI.enableAnimationsWinJS.UI.disableAnimations 函数。

优化动画性能

通过动画体现应用的响应性

提供良好的整体用户体验,你的应用应该让人感觉到快速并具有很高的用户操作响应性。如果使用得当,动画可以在适当的时间向用户提供适当的反馈,使用户感觉你的应用具有更好的响应性。

响应用户操作的动画必须能尽快启动。这一点很重要,它向用户表明他们的操作是成功的,正在进行相应处理。如果还需要进一步操作(例如加载一个新页面)才能完成过渡,则应在用户响应动画已触发后再执行该操作。

使用独立动画

JavaScript 应用的动画平台支持在独立于 UI 线程的硬件加速单独系统线程中运行某些特定类型的动画。这类动画称为“独立动画”。在 UI 线程中运行的动画称为从属动画。由于独立动画不必与 UI 线程中发生的其他操作竞争资源,因此独立动画普遍比从属动画更平滑。

动画库中的所有动画均可以作为独立动画来运行,但是若要这样做,你在应用的实现中必须注意到几个考虑事项。有关如何确保你的动画函数调用可以有效地作为独立动画运行的详细信息,请参阅独立组合:在 Internet Explorer 中呈现和组合

尽量减少同时发生动画操作的元素数量

尽量减少发生动画操作的单个元素数量。例如,尽量不要向某个动画传递一组元素,而只向该动画传递这些元素的父元素,因为这样动画引擎便将只需创建一个动画操作。

使用默认偏移

对于包含偏移参数的动画库动画,请尽量使用默认偏移。这样你不仅将获得该动画的设计推荐转换,同时由于该动画可以使用预计算的关键帧,因而其性能也会更好。

默认偏移也将自动在从右到左的应用中实现镜像;对于某些动画,默认偏移将在调整应用大小时自动更改转换量,以便显示适合较窄视图状态的效果。

创建自定义动画

你应该尽可能使用动画库动画。但是,如果你的方案很独特,内置的所有动画都不符合你的需求,则可以创建自定义动画。

在 JavaScript 应用中实现自定义动画的方法有两种:通过标准的 CSS3 动画和过渡,或者通过动画库的帮助函数 executeAnimationexecuteTransition

使用标准 CSS3 动画和过渡创建自定义动画

CSS3 动画和过渡支持一个灵活的选项,可以针对多个 CSS 属性创建动画或过渡。有关详细信息,请参阅动画过渡主题。

当你选择创建自己的动画时,请注意以下几点:

  • 某些 CSS 属性的动画或过渡不会作为独立动画运行,并且可能会导致针对每个帧都重绘整个页面。这可能会导致动画缓慢并出现抖动,而这种情况属于不良的用户体验。为确保你的动画能够独立运行,在实现你的自定义动画时,应避免对此类属性使用动画。
  • 针对同一个元素,不能同时存在自定义 CSS3 动画/过渡和动画库动画。

使用 executeAnimation 和 executeTranslation 创建自定义动画

动画库使用动画库函数 executeAnimationexecuteTransition 来运行其自有动画,你也可以对自定义动画使用这两个函数。使用这两个函数执行的动画和过渡均可以有效地作为独立动画来运行,并且可以与任何也在运行的现有动画库动画同时存在。executeAnimationexecuteTransition 函数返回 Promise 对象,与其他动画库函数相一致。

你可以对任何可以使用动画的 CSS 属性使用这两个函数。但是,只有不透明度和转换属性可以作为独立动画运行。如果你的应用需要一些较另类的特色(例如游戏内动画),那么这两个函数可能并不适用于你的方案。

在使用 executeAnimation 函数时,建议你为动画指定关键帧,以实现更好的性能。



                                
@keyframes custom-opacity-in    { from { opacity: 0; } to { opacity: 1; } }
                            

下面的示例演示了自定义动画。



                                
function runCustomShowAnimation() {
    var showAnimation = WinJS.UI.executeAnimation(
        target,
        {
            keyframe: "custom-opacity-in",
            property: "opacity",
            delay: 0,
            duration: 500,
            timing: "linear",
            from: 0,
            to: 1
        }
    );
}
                            

下面的示例演示了自定义过渡



                                
function runCustomShowTransition() {
    var showTransition = WinJS.UI.executeTransition(
        target,
        {
            property: "opacity",
            delay: 0,
            duration: 500,
            timing: "linear",
            to: 1
        }
    );
}
                            

组合自定义动画和过渡

你可以通过组合动画和过渡来创建自定义情节提要。下面的示例将动画和过渡进行组合,在目标元素上同步实现了淡入和滑动的效果。情节提要的两个部分分别通过调用 executeAnimationexecuteTransition 而独立触发,但是这两个部分将同时开始。



                                
@keyframes custom-translate-in    { from { transform: translateY(50px); } to { transform: none; } }
                            



                                
function runCustomShowStoryboard() {
    var promise1 = WinJS.UI.executeAnimation(
        target,
        {
            keyframe: "custom-translate-in",
            property: "transform",
            delay: 0,
            duration: 367,
            timing: "cubic-bezier(0.1, 0.9, 0.2, 1)",
            from: "translate(50px)", 
            to: "none"
        });
    var promise2 = WinJS.UI.executeTransition(
        target,
        {
            property: "opacity",
            delay: 0,
            duration: 167,
            timing: "linear",
            to: 1
        });
    return WinJS.Promise.join([promise1, promise2]);
}
                            

相关主题

创建 UI 动画 (HTML)

 

 

显示:
© 2014 Microsoft