Quantcast
Channel: w3cplus
Viewing all articles
Browse latest Browse all 1557

Web动画

$
0
0

动画是使 Web 应用和网站吸引人的重要因素。 用户希望有快速响应和高度交互的用户界面。 但是,为界面设置动画未必很简单。 什么应设置动画,何时显示,以及动画应有哪种感觉?

使用动画作为一种给项目增加活力的方式。动画应支持用户交互。要注意设置动画的属性;有一些属性比其他属性开销更大!

选择合适的内容来设置动画

出色的动画可增添一层享受,增加项目对用户的吸引力。 可以将您喜欢的几乎所有内容设置动画,不管是宽度、高度、位置、颜色、背景,但您需要注意潜在的性能瓶颈,以及动画将如何影响您的应用的个性。 卡顿或选择不当的动画可能对用户体验产生负面影响,因此动画需要高性能并且恰当。

使用动画来支持交互

不要仅仅因为您可以做动画就随便做;它只会惹恼用户并妨碍操作。 相反,要有策略地放置动画以增强用户交互。 如果用户点击菜单图标,则让菜单从页面侧边伸出,或如果他们点击按钮,则可以使用少量辉光或弹跳来确认交互。 注意避免不必要地打断或妨碍用户活动的动画。

避免为开销大的属性设置动画

唯一比错误放置的动画更糟的事情是导致页面卡顿的动画。 这将让用户觉得失望和不悦,并且可能希望您根本不必费心去设置动画!

改变一些属性的开销比改变其他属性要多,因此更可能使动画卡顿。 因此,例如,与改变元素的文本颜色相比,改变元素的box-shadow将需要开销大很多的绘图操作。 改变元素的width可能比改变其transform要多一些开销。

您可以在动画和性能指南中阅读有关动画性能考虑事项的更多内容,但是如果想要TL;DR,则坚持使用转换和透明度改变,以及利用will-change。 如果想确切知道给指定的属性设置动画会触发什么效果,请查阅CSS 触发器

CSS 触发器

CSS 对比 JavaScript 动画

有两种主要方法在网页上创建动画:使用 CSS 和使用 JavaScript。 您选择哪种方法实际上取决于项目的其他依赖关系,以及您尝试实现什么类型的效果。

使用 CSS 动画来实现较简单的“一次性”转换,例如切换 UI 元素状态。当您想要高级效果时,例如弹跳、停止、暂停、倒退或减速,则使用 JavaScript 动画。如果选择使用 JavaScript 来编写动画,可选用 TweenMax,或者如果想要更轻量的解决方案,则使用 TweenLite。

大多数基本动画可以使用 CSS 或 JavaScript 来创建,但工作量和时间将有所不同 (另请参考CSS 对比 JavaScript 性能)。 每种方法都各有利弊,但是以下是很好的经验法则:

  • 当您为 UI 元素采用较小的独立状态时,使用 CSS。 CSS 转换和动画非常适合于从侧面引入导航菜单,或显示工具提示。 最终,可以使用 JavaScript 来控制状态,但动画本身是采用 CSS。
  • 在需要对动画进行大量控制时,使用 JavaScript。 动态跟踪触摸位置的动画,或需要停止、暂停、减速或倒退的动画一般需要使用 JavaScript。 如果您已使用包括了动画功能的 jQuery 或 JavaScript 框架,则可能发现继续使用该方法来做动画在总体上更方便,而不是切换到 CSS。

如果您已使用包括了动画功能的 jQuery 或 JavaScript 框架,则可能发现继续使用该方法来做动画在总体上更方便,而不是切换到 CSS。

使用 CSS 编写动画

使用 CSS 编写动画无疑是使事物在屏幕上移动的最简单方式。

以下是一些 CSS 代码,让一个元素同时在 X轴和 Y轴上移动 100px。 其实现方法是使用 CSS 转换,用时设置为 500ms。 当添加了move类时,transform值被改变并且转换开始。

.box {
    -webkit-transform: translate(0, 0);
    -webkit-transition: -webkit-transform 500ms;

    transform: translate(0, 0);
    transition: transform 500ms;
}

.box.move {
    -webkit-transform: translate(100px, 100px);
    transform: translate(100px, 100px);
}

除了转换的持续时间之外,还有针对缓动的选项,缓动基本上是动画表现的方式。 您可以在“缓动的基础知识”指南上了解更多信息。

如果在上述代码段中,创建单独的 CSS 类来管理动画,则可以使用 JavaScript 来打开和关闭每个动画:

box.classList.add('move');

这样将为应用实现很好的平衡。 您可以侧重于使用 JavaScript 来管理状态,只需在目标元素上设置相应的类,让浏览器去处理动画。 如果您按照这种方法,则可以侦听元素的transitionend事件,但前提是您能够放弃对 Internet Explorer 较旧版本的支持;IE10 是支持这些事件的首个版本。 所有其他浏览器均已支持此事件有一段时间了。

侦听转换结束所需的 JavaScript 如下:

var box = document.querySelector('.box');
box.addEventListener('transitionend', onTransitionEnd, false);

function onTransitionEnd() {
  // Handle the transition finishing.
}

除了使用 CSS 转换之外,还可以使用 CSS 动画,这允许您对单个动画关键帧、持续时间和迭代进行更多控制。

如果您是动画初学者,那么说明一下,关键帧是来自手绘动画的老术语。 动画设计者为一个片段创建多个特定帧,称为关键帧,关键帧将提供某个动作的起止状态,然后它们开始绘出关键帧之间的所有单个帧。 现在我们使用 CSS 动画也有相似的过程,我们指示浏览器,CSS 属性在指定时点需要什么值,然后浏览器填充其中的间隔。

例如,可以使用与转换相同的方式为方框设置动画,但是设置动画时没有任何用户交互(例如点击),而是采用无限重复。 还可以同时更改多个属性:

.box {
    animation-name: movingBox;
    animation-duration: 1300ms;
    animation-iteration-count: infinite;
    animation-direction: alternate;
}
@keyframes movingBox {
    0% {
        transform: translate(0, 0);
        opacity: 0.3;
    }

    25% {
        opacity: 0.9;
    }

    50% {
        transform: translate(100px, 100px);
        opacity: 0.2;
    }

    100% {
        transform: translate(30px, 30px);
        opacity: 0.8;
    }
}

借助 CSS 动画,可独立于目标元素来定义动画本身,并且使用 animation-name属性来选择所需的动画。

CSS 动画大部分仍采用供应商前缀,Chrome、Safari、Opera、Safari Mobile 和安卓浏览器中使用-webkit-。 Internet Explorer 和 Firefox 均不采用前缀。 许多工具可帮助您创建所需的 CSS 前缀版本,使您能够在源文件中编写无前缀的版本。

使用 JavaScript 编写动画

比较而言,使用 JavaScript 创建动画比编写 CSS 转换或动画更复杂,但它一般可为开发者提供更多功能。 一般方法是使用requestAnimationFrame,在动画的每个帧上,手动确定正在设置动画的元素的每个属性值。

您可能看到网页上很多使用 setIntervalsetTimeout来实现动画的代码。 这是个馊主意,因为动画不会与屏幕的刷新率同步,并且很可能出现抖动和跳帧。 务必要避免使用此类代码,而是使用可以正确同步的 requestAnimationFrame

以下是在重新创建我们之前所讨论的 CSS 转换时需要编写的 JavaScript。

function Box () {
    var animationStartTime = 0;
    var animationDuration = 500;
    var target = document.querySelector('.box');

    this.startAnimation = function() {
        animationStartTime = Date.now();
        requestAnimationFrame(update);
    };

    function update() {
        var currentTime = Date.now();
        var positionInAnimation = (currentTime - animationStartTime) / animationDuration;

        var xPosition = positionInAnimation * 100;
        var yPosition = positionInAnimation * 100;

        target.style.transform = 'translate(' + xPosition + 'px, ' + yPosition + 'px)';

        if (positionInAnimation <= 1)
            requestAnimationFrame(update);
        }
    }

    var box = new Box();
    box.startAnimation();

当您尝试进行扩展以包括更多用例时,此代码开始变得很复杂并且难以管理,因此,一般来说,从许多可用于动画的 JavaScript 库中选择一个会比较好。 如果您已在项目中使用 jQuery,继续使用它并使用.animate()函数也比较好。 另一方面,如果您需要专门的库,则可以看看Greensock’s TweenMax,这个库非常强大。 它有一个轻量化版本,称为 TweenLite,从文件大小角度来看更加友好。

由于使用 JavaScript 动画您可以完全控制元素在每个步骤的样式,因此在您认为合适时可以减慢动画、暂停、停止、倒退以及操纵它。

缓动的基础知识

自然界中没有东西是从一点呈线性地移动到另一点。 现实中,事物在移动时可能加速或减速。 我们的大脑习惯于期待这种运动,因此在做动画时,应利用此规律。 自然的运动将使用户对您的应用感觉更舒适,从而产生更好的总体体验。

缓动使您的动画感觉更自然。为 UI 元素选择缓出动画。避免缓入或缓入缓出动画,除非可以使其保持简短;这类动画可能让最终用户觉得很迟钝。

在经典动画中,缓慢开始然后加速的动画术语是“慢入”,快速开始然后减速的动画被称为“慢出”,但是网络上对于这些动画最常用的术语分别是“缓入”和“缓出”。 有时两种动画组合,称为“缓入缓出”。 缓动实际上是使动画不再那么尖锐或生硬的过程。

缓动关键字

CSS 变换和动画都允许您选择要为动画使用的缓动类型。 您可以使用影响相关动画的缓动(或有时称为定时)的关键字。 还可以完全自定义您的缓动,使您能更自由地表达应用的个性。

以下是可在 CSS 中使用的一些关键字:

  • linear
  • ease-in
  • ease-out
  • ease-in-out

资料来源:CSS 变换,W3C

还可以使用steps关键字,它允许您创建具有离散步骤的变换,但上面列出的关键字对于创建感觉自然的动画最有用,并且这正是您要的东西。

线性动画

没有任何缓动的动画被称为线性动画。 线性变换的图形看起来像这样:

线性动画的曲线

随着时间推移,其值以等量增加。 采用线性运动时,事物常常让人觉得像机器人,不自然,这也是用户会觉得不协调的东西。 一般来说,应避免线性运动。

不管通过 CSS 还是 JavaScript 来编写动画,您将发现始终有线性运动的选项。 要通过 CSS 实现上述效果,代码将类似以下:

transition: transform 500ms linear;

缓出动画

缓出使动画在开头处比线性动画更快,并且还会在结尾处减速。

缓出动画的曲线

有很多方法来实现缓出效果,但最简单的方法是 CSS 中的ease-out关键字:

transition: transform 500ms ease-out;

缓出一般最适合用户界面,因为开头时快速使动画有反应快的感觉,同时在结尾仍允许有一点自然的减速。

缓入动画

缓入动画开头慢结尾快;与缓出正好相反。

缓入动画的曲线

这种动画像沉重的石头掉落一样,开始时很慢,然后快速地重重撞击地面,突然沉寂下来。

要使用缓入动画,与缓出和线性动画类似,可以使用其关键字:

transition: transform 500ms ease-in;

但是,从交互的角度来看,缓入可能让人感觉有点不寻常,因为结尾很突然;在现实中移动的事物往往是减速,而不是突然停止。 缓入还有让人感觉行动迟缓的不利效果,这会对网站或应用的响应速度给人的感觉产生负面影响。

缓入缓出动画

缓入并缓出与汽车加速和减速相似,使用得当时,可以实现比单纯缓出更生动的效果。

缓入缓出动画的曲线

必须注意,由于缓入开头让动画有迟钝感,动画时间不要过长。 一般 300 - 500毫秒的范围比较合适,但很大程度上要根据项目的感觉来使用准确的数字。 也就是说,由于开头慢、中间快和结尾慢,最终动画将有更强的对比,可能让用户感到非常满意。

要设置缓入缓出动画,可以使用ease-in-out CSS 关键字:

transition: transform 500ms ease-in-out;

自定义缓动

有时您不想使用 CSS 随附的缓动关键字,或者要使用基于 JavaScript 的动画库。 在这两种情况下,一般可以定义自己的曲线(或公式),这让您能更好地控制项目动画的感觉。

自定义缓动使您能够给项目提供更多个性。您可以创建与默认动画曲线(缓出、缓入等)相似的三次贝塞尔曲线,只是重点放在不同的地方。当需要对动画时间和行为(例如弹性或弹跳动画)进行更多控制时, 使用 JavaScript。

如果使用 CSS 编写动画,您将发现可以通过定义三次贝塞尔曲线来定义时间。 事实上,关键字easeease-inease-outlinear映射到预定义的贝塞尔曲线,详细说明请参考 CSS 过渡规范

在 CSS 中,这些贝塞尔曲线有四个值,即 2对数字,每对数字描述三次贝塞尔曲线的控制点的 XY坐标。 贝塞尔曲线的起点坐标为 (0, 0),终点坐标为 (1, 1);由您设置两个控制点的 XY值。 两个控制点的 X值必须在 01之间,每个控制点的 Y值可以超过 [0, 1]限制,但此规范未说明可超过多少!

更改每个控制点的 XY值将实现截然不同的曲线,从而使动画有截然不同的感觉。 例如,如果第一个控制点在右下角,则动画在开头缓慢。 如果它在左上角,动画在开头会显得很快。 相反,如果第三控制点在网格的右下角,则动画在结尾处变快,而在左上角时,动画将在结尾处变慢。

为了对比,以下有两条曲线:一条典型的缓入缓出曲线和一条自定义曲线:

缓入缓出曲线

此自定义曲线的 CSS 为:

transition: transform 500ms cubic-bezier(0.465, 0.183, 0.153, 0.946);

前两个数字是第一个控制点的 XY坐标,后两个数字是第二个控制点的 XY坐标。

制作自定义曲线很有趣,它让您对动画的感觉进行更多控制。 以上述曲线为例,您可以看到曲线与经典的缓入缓出曲线相似,但缓入即“开始”部分缩短,而结尾减速部分拉长。

使用此动画曲线工具进行试验,并查看此曲线如何影响动画的感觉。

另外推荐一个优秀的cubic-bezier在线制作工作:

cubic-bezier

使用 JavaScript 实现更多控制

有时您需要三次贝塞尔曲线未能提供的更多控制。 可能您想要弹跳的感觉,或希望在中途停止执行动画,这两种情况要通过 CSS 实现都更加困难。 在这种情况下,应当使用 JavaScript 动画库。 其中一个最佳的库是Greensock’s TweenMax (或 TweenLite,如果您想要超轻量版本),您可以在小型 JavaScript 库中获得很多控制,它是一个非常成熟的代码库。

要使用 TweenMax 之类的代码,可在页面中包括其脚本:

<script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/latest/TweenMax.min.js"></script>

到达合适位置后,您可以对元素调用 TweenMax,并且告诉它您想要的任何缓动,以及您想要哪些属性。 有大量缓动选项可供使用;以下代码使用一个弹性缓出:

var box = document.getElementById('my-box');
var animationDurationInSeconds = 1.5;

TweenMax.to(box, animationDurationInSeconds, {
    x: '100%',
    ease: 'Elastic.easeOut'
});

TweenMax 文档重点说明了您使用的所有选项,因此非常值得一读。

选择合适的缓动

前面已经讨论了可在动画中实现缓动的各种选项,您应当在项目中使用哪种?您的动画应采用哪种持续时间?

为 UI 元素使用缓出动画;Quintic 缓出是一个非常好(虽然比较活泼)的缓动。一定要使用动画持续时间;缓出和缓入应为 200ms-500ms,而弹跳和弹性缓动应为更长的持续时间,800ms - 1200ms

一般来说,缓出将是正确选择,并且必定是很好的默认选择。 它开头较快,使动画有反应快速的感觉,这是受欢迎的,但在结尾有一个不错的减速。

除了在 CSS 中通过ease-out关键字指定的公式之外,还有一组知名的缓出公式,它们按其“攻击性”排列。 如需超活泼的缓出效果,可考虑Quintic 缓出

Quintic 缓出动画的曲线

其他缓动公式应谨慎使用,特别是弹跳或弹性缓动,并且仅在适合于项目时才使用。 很少有东西会像不协调的动画那样让用户体验很差。 如果项目不是欢乐有趣的类型,则不要让 UI 元素到处蹦!反过来,如果是制作一个理应欢乐有趣的网站,则想尽办法让它蹦蹦跳!

试试各种缓动,看看哪些与项目的个性匹配,然后以此为起点。 easings.net上可找到完整的缓动类型列表以及演示。

选择合适的动画持续时间

给项目添加的任何动画必须有正确的持续时间。 若太短,动画让人感觉有攻击性和突然;若太长,则让人觉得梗阻和讨厌。

  • 缓出:约 200ms - 500ms。 这让眼睛有机会看到动画,但不会觉得梗阻。
  • 缓入:约 200ms - 500ms。 记住,它在结尾将晃动,没有时间量变化将缓和这种感觉。
  • 弹跳或弹性效果:约 800ms - 1200ms。 您需要留出时间让弹性或弹跳效果“停下”。 若没有这点额外时间,动画的弹性跳动部分将让眼睛觉得有攻击性和不愉快。

当然这些只是指南。 用您自己的缓动做试验,然后选择觉得适合于项目的缓动。

不对称的动画定时

使动画持续时间不对称,可让您表达个性的同时快速响应用户交互,从而有助于提升用户体验。 还能使感觉出现对比,使界面在视觉上更吸引人。

使用不对称的动画定时为作品增加个性和对比效果。务必有利于用户交互;当响应点击时采用较短的持续时间,其他情况则可以留出较慢的持续时间。

与大多数动画“规则”一样,应当尝试各种方法,以找出什么适合于您的应用,但是涉及用户体验时,用户是最不耐烦的。 经验法则是始终快速响应用户交互。 也就是说,大多数时候用户操作是不对称的,因此动画也可以不对称。

例如,当用户点击以显示侧栏导航时,您应当尽快将其放入屏幕,持续时间约 100ms。 但是,当用户消除菜单时,您可以让视图动画离开得慢一点,即大约 300ms

相比之下,在显示模态视图时,一般是显示错误或一些其他关键消息。 在这种情况下,要慢一点显示视图,同样大约为 300ms,但是在消除(由用户触发)时,应非常快地完成。

那么一般经验法则是:

  • 对于用户交互触发的 UI 动画,例如视图变换或显示元素,采用快速前奏(短持续时间)和慢速结尾(较长持续时间)。
  • 对于由代码触发的 UI 动画,例如错误或模态视图,采用较慢前奏(较长持续时间)和快速结尾(短持续时间)。

动画与性能

每次在设置动画时必须注意保持 60fps,因为任何卡顿或停顿都会引起用户注意,并对体验产生负面影响。

注意您的动画不能导致性能问题;确保了解将指定 CSS 属性设置动画的影响。改变页面(布局)结构或导致绘图的动画属性特别消耗资源。尽可能坚持改变变形和透明度。使用will-change来确保浏览器知道您打算对什么设置动画。

给属性设置动画不是免费的,给一些属性设置动画的开销比其他属性要小。 例如,给元素的widthheight设置动画会改变其几何形状,并且可能导致页面上的其他元素移动或改变大小。 此过程称为布局(在 Firefox 等基于 Gecko 的浏览器中称为重排),如果页面有很多元素,则可能开销很大。 每当触发布局时,页面或其一部分通常需要进行绘制,这一般比布局操作本身更消耗资源。

应尽可能避免给触发布局或绘制的属性设置动画。 对于大部分现代浏览器,这意味着将动画限制为opacitytransform,两种都可经浏览器高度优化;动画由 JavaScript 还是由 CSS 处理并不重要。

使用 will-change 属性

可以使用 will-change来确保浏览器知道您打算改变元素的属性。 这使浏览器能够在您做出更改之前,进行最合适的优化。 但是必须注意,不要过度使用will-change,因为它可能导致浏览器浪费资源,从而导致更多性能问题。

一般经验法则是,如果动画可能在接下来的 200ms内触发(由用户交互触发或由应用的状态触发),则对动画元素使用 will-change是个好主意。 对于大多数情况,在应用的当前视图中您打算设置动画的任何元素都应启用will-change,无论您打算改变哪个属性。 在我们在之前的指南中一直使用的方框示例中,为变形和透明度加上will-change属性将产生如下结果:

.box {
    will-change: transform, opacity;
}

现在支持此属性的浏览器有 Chrome、Firefox 和 Opera,这些浏览器将在后台进行相应的优化,以支持这些属性的更改或动画。

CSS 对比 JavaScript 的性能

网络上有很多网页和评论从性能的角度讨论了 CSS 和 JavaScript 动画的相对优点。 以下是要记住的几个要点:

  • 基于 CSS 的动画一般由浏览器“主线程”之外的独立线程处理,在其中执行样式、布局、绘制和 JavaScript。 这意味着,如果浏览器正在主线程上运行一些高开销任务,则基于 CSS 的动画可以继续运行而不中断。 在许多情况下,变形和透明度的更改可由处理 CSS 动画的相同线程(称为“组合线程”)来处理,因此,您最好应坚持使用这些属性来设置动画。
  • 如果任何动画触发绘制、布局或同时触发这两者,则“主线程”将必须执行工作。 这点同时适用于 CSS 和 JavaScript 动画,并且布局或绘制的开销可能拖慢与 CSS 或 JavaScript 执行相关的任何工作,使问题变得无意义。

如果想准确知道给指定属性设置动画会触发哪种工作,请查看CSS 触发器了解详细信息。

特别声明:上面的内容将@Paul Lewis@Sam Thorogood的几个Topics串在一起。并非原创文章,如果需要转载,请注明文章出处。

除了上面这几篇文章,还有另外两篇文章也值得一读《在视图之间设置动画》和《给模态视图设置动画

大漠

常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。中国Drupal社区核心成员之一。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《图解CSS3:核心技术与案例实战》。

如需转载,烦请注明出处:http://www.w3cplus.com/animation/animations.html


Viewing all articles
Browse latest Browse all 1557

Trending Articles