了解 CSS 动画和过渡的缓动函数

已发表: 2022-03-10
快速总结↬缓动函数可以通过影响动画的速率或速度来改变动画的外观和感觉。 作为人类,我们习惯于自然的非线性运动。 在动画中使用这些自定义缓动功能可以改善用户印象和更愉快的用户体验。 在本文中,我们将深入探讨缓动函数,看看我们如何使用它们来创建那些自然而令人惊叹的动画。

你有没有注意到一个制作精良的专业项目的动画看起来是多么流畅和令人愉快? 我想起了 In Pieces 网站,其中动画不仅用于装饰,而且还以有影响力的方式传达有关濒临灭绝物种的信息。 不仅动画设计和风格优美,而且流畅和谐。 正是这种流动与设计和演示相结合,使动画看起来令人惊叹和自然。 这就是缓动函数的威力,也称为计时函数。

在 CSS 中编写过渡和动画属性时,我们通常会使用预定义的缓动函数,比如ease-out因为它很简单,看起来还不错,并且在大多数情况下都能很好地工作。 但是,如果页面上有十几个或更多元素的动画具有相同的持续时间和缓动函数值,可能会使 UI 有点乏味和单调。 人类对自然运动的反应更好,因此使动画和过渡更加多样化和自然将带来更好的用户体验。

如果我们回到 In Pieces 示例并检查样式表,我们会注意到各种自定义cubic-bezier函数与预定义的linear ease-in计时函数结合使用,以实现漂亮的动画流程。 如果只使用预定义的缓动函数而不是自定义缓动函数,动画看起来不会那么好。 以下视频展示了 In Pieces 网站,其中所有缓动功能都设置为ease-out 。 尽管动画没有任何问题,但请注意它们并不像原始动画那样令人惊叹或令人兴奋。

在本文中,我们将深入探讨 CSS 缓动函数、缓动函数的类型以及如何使用三次贝塞尔曲线创建自定义缓动函数。

跳跃后更多! 继续往下看↓

引擎盖下

为了更好地理解缓动函数,我们需要退后一步,看看 CSS 中的动画基础知识。

动画由关键帧定义,这些关键帧决定元素的外观和在特定点的位置。 CSS 过渡使用两个关键帧(开始值和结束值),而 CSS 动画允许使用@keyframes规则进行更精确的控制。

从左到右从 0px(0% 动画输出)移动到 500px(100% 动画输出)的框的动画输出(关键帧)示例
从左到右从 0px(0% 动画输出)移动到 500px(100% 动画输出)的框的动画输出(关键帧)示例。 (大预览)

动画持续时间决定了动画从第一个关键帧到最后一个关键帧的时间量。 下图显示了动画关键帧和持续时间之间的联系。

一个盒子的动画输出示例,它从 0px(0% 动画输出)移动到 500px(100% 动画输出),持续时间为 1000 毫秒。两点由直线连接。
一个盒子的动画输出示例,它从 0px(0% 动画输出)移动到 500px(100% 动画输出),持续时间为 1000 毫秒。 两点由直线连接。 (大预览)

动画可以通过多种方式在两个关键帧之间进行。 例如,动画可以有一个恒定的速度,或者它可以在开始时快速移动并在接近结束时减速,或者在开始时缓慢移动然后加速直到到达终点,等等。这个速率或速度定义为缓动功能(计时功能) 。 如果我们看一下上图,缓动函数由连接两点的线的形状表示。 我们在前面的例子中使用了线性函数(直线),但我们也可以使用曲线来连接关键帧。

从 0px(第一个关键帧)移动到 500px(最后一个关键帧)且持续时间为 1000 毫秒的框的动画输出示例。动画将在起始关键帧处加速并在最后一个关键帧附近减速。
从 0px(第一个关键帧)移动到 500px(最后一个关键帧)且持续时间为 1000 毫秒的框的动画输出示例。 动画将在起始关键帧处加速并在最后一个关键帧附近减速。 (大预览)

如您所见,动画缓动函数有很多可能的选项和变体,接下来我们将看看它们。

缓动函数的类型

在 CSS 中可以使用三种主要类型的缓动函数:

  • 线性函数( linear ),
  • 三次贝塞尔函数(包括ease , ease-in , ease-outease-in-out ),
  • 楼梯功能( steps )。

线性函数

我们已经在前面的一个示例中介绍了线性函数,所以让我们快速回顾一下。 使用线性定时功能,动画以恒定速度通过关键帧。 您可能已经知道,线性定时功能可以通过使用linear关键字在 CSS 中轻松设置。

一个盒子的动画输出示例,它从 0px(0% 动画输出)移动到 500px(100% 动画输出),持续时间为 1000 毫秒。
一个盒子的动画输出示例,它从 0px(0% 动画输出)移动到 500px(100% 动画输出),持续时间为 1000 毫秒。 (大预览)
从 0px(第一个关键帧)移动到 200px(第二个关键帧)然后到 500px(最终关键帧)的框的动画输出示例,持续时间为 1000 毫秒。
从 0px(第一个关键帧)移动到 200px(第二个关键帧)然后到 500px(最终关键帧)的框的动画输出示例,持续时间为 1000 毫秒。 (大预览)

请参阅 Adrian Bece 的钢笔 [动画 - 线性](https://codepen.io/smashingmag/pen/Bapbgxg)。

请参阅 Adrian Bece 的钢笔动画 - 线性。

三次贝塞尔函数

虽然线性计时函数有其用例,但如果使用不当或过于频繁,它们会使动画看起来平淡无奇和不自然。 正如我们从 In Pieces 示例中看到的那样,用户对自然运动的反应更好,即可以加速和减速的非线性计时函数。

贝塞尔曲线常用于矢量图形、动画和机器人技术,以轻松创建平滑曲线和轨迹。 在 CSS 中,我们使用由四个点定义的贝塞尔曲线,称为三次贝塞尔曲线。

常用的预定义缓动函数如easeease-inease-outease-in-out属于 Cubic Bezier 函数。 它们可以用作设置非线性缓动函数的快速方法。 甚至可以使用cubic-bezier函数定义线性函数。

缓动功能cubic-bezier启动速度中速结束速度
linear cubic-bezier(0.0, 0.0, 1.0, 1.0) 持续的持续的持续的
ease cubic-bezier(0.25, 0.1, 0.25, 1.0) 快速加速快速加速慢加速
ease-in cubic-bezier(0.42, 0, 1.0, 1.0) 慢加速快速加速全速
ease-out cubic-bezier(0, 0, 0.58, 1.0) 全速慢加速慢加速
ease-in-out cubic-bezier(0.42, 0, 0.58, 1.0) 慢加速全速快速加速

尽管预定义的值在许多情况下都适用,但知道如何创建自定义三次 Bezier 函数可以让您更好地控制动画的外观和感觉,从而使动画看起来更加令人印象深刻和有影响力。

在以下示例中,我编辑了 In Pieces 示例的动画以使用具有不同值的不同 Cubic Bezier 函数。 您可以使用此缓动功能看到动画的外观和感觉有多么不同。

 cubic-bezier(0, 1.2, 1, 0.2)

让我们看一下在 CSS 中用于定义 Cubic Bezier 曲线的cubic-bezier函数。 三次贝塞尔函数由四个点(x 和 y 坐标对)定义,但我们在cubic-bezier贝塞尔函数中只定义了 2 个点。 这是为什么?

CSS 动画的三次贝塞尔曲线示例。
CSS 动画的三次贝塞尔曲线示例。 (图片来源:MDN Web docs)(大预览)

这是因为第一个点 (P0) 和最后一个点 (P3) 固定在曲线的开始(初始动画状态)和结束(最终动画状态),因为动画需要在指定的关键帧和指定的范围内结束期间。 使用剩下的两个点(P1 和 P2),我们可以微调函数的曲线和缓动,从而获得非线性动画速度。

 cubic-bezier(x1, y1, x2, y2)

X 坐标( x1x2 )表示时间比例,并且限制在 0 和 1 之间的值(动画不能比指定的更早或持续时间更长),而 Y 坐标( y1y2 )表示动画输出及其值,它们是通常设置在 0 和 1 之间,但不限于该范围。 我们可以使用 0 和 1 范围之外的y1y2值来创建弹跳效果。

具有弹跳效果的动画
(大预览)

如果动画由几个关键帧组成,在 CSS @keyframes属性中定义,缓动函数将应用于两点之间的每条曲线。 如果我们将ease-out功能应用于具有 3 个关键帧的动画,动画将在第一个关键帧开始处加速,并在第二个关键帧附近减速,并且下一对关键帧(第二个关键帧和最后一个关键帧)。

请参阅 Adrian Bece 的 Pen [Cubic-bezier functions 2 keyframes](https://codepen.io/smashingmag/pen/zYNbVME)。

请参阅 Adrian Bece 的 Pen Cubic-bezier functions 2 keyframes。

注意缓动函数是如何在每个关键帧对之间重复的——第一个和第二个关键帧(第一对),第二个关键帧和最后一个关键帧(第二对)。 前面和下面的示例的动画持续时间相同。

请参阅 Adrian Bece 的 Pen [Cubic Bezier functions 3 keyframes](https://codepen.io/smashingmag/pen/KKaEjbM)。

请参阅 Adrian Bece 的 Pen Cubic Bezier 函数 3 个关键帧。

创建这些函数可能是一项复杂的任务,因此您可能不会通过猜测cubic-bezier参数来调整坐标。 您必须使用一种工具来帮助您确定这些神奇的数字,以便创建一个完全适合您的动画的计时功能。 幸运的是,有许多浏览器和在线工具可以帮助我们。 我们将在本文的以下部分之一中讨论它们。

楼梯功能

楼梯函数使动画能够以非连续方式在特定数量的帧之间跳转。 你可以把它想象成一个“滴答”的动画。

例如,如果我们看一下前面的示例,其中一个框从 0px 移动到 500px,并且我们将动画限制为 5 步,动画将在以下 5 个关键帧之间跳转——0px、100px、200px、300px 和 400px职位。

我们可以通过 CSS 中的steps功能轻松实现这一点。

 steps(number_of_frames)
 steps(5)

此函数有一个附加选项,用于控制包含哪些关键帧。 正如你从前面的例子中看到的,一个盒子从 0px 移动到 500px 5 步的动画将在 400px 的位置结束。 如果我们希望动画从 100px 开始并在 500px 位置结束,我们可以使用jump term选项作为第二个参数。 跳转项影响如何从动画时间轴中选择关键帧。

 steps(number_of_frames, jump_term)
 steps(5, jump-start)

在 CSS steps函数中可以使用以下跳转项选项:

  • jump-start
    动画从起点直接跳转,起点不可见 t。 在我们的示例中,关键帧将是 100px、200px、300px、400px、500px。
  • jump-end
    最后一次跳转发生在动画结束且不可见时。 在我们的示例中,关键帧将是 0px、100px、200px、300px、400px。
  • jump-both
    第一次和最后一次跳跃都将分别在动画开始和结束时发生,因此它们不可见。 所有 5 次跳跃都将发生在凝视点和结束点之间。 在我们的示例中,这些关键帧将是 80px、165px、250px、335px、420px。
  • jump-none
    第一次和最后一次跳跃都是可见的。 在我们的示例中,这些关键帧将是 0px、125px、250px、375px、500px。
持续时间为 1000 毫秒的步骤 (5) 动画的时间轴
step(5) 动画的时间轴,持续时间为 1000 毫秒。 (大预览)

以下示例展示了各种跳转项如何影响动画行为。 不同的跳跃项应用于具有相同持续时间的 5 步动画。

请参阅 Adrian Bece 的 Pen [Step function](https://codepen.io/smashingmag/pen/ZELPdPK)。

请参阅 Adrian Bece 的 Pen Step 功能。

调试动画和有用的工具

正如我们从 Cubic Bezier 示例中看到的那样,我们需要某种工具来帮助我们微调 Cubic Bezier 曲线参数,以便我们可以实现我们想要的动画的外观和感觉。

在本节中,我们将了解应该帮助我们做到这一点的浏览器工具、网站和 CSS 样式。

浏览器工具

浏览器开发者工具提供了开箱即用的有用的缓动函数编辑特性。 请注意,只有三次 Bezier 函数可用于编辑。 这些工具提供了快速简单的动画预览,以便开发人员能够获得即时反馈并微调缓动功能。

铬,Safari,火狐。
铬,Safari,火狐。 (大预览)

Chrome、Safari 和 Firefox 还在开发者工具中提供了一个专门的动画选项卡,提供更详细的概述,包括动画属性、持续时间、时间线、关键帧、延迟等。

铬,Safari,火狐。
铬,Safari,火狐。 (大预览)

有用的工具和网站

有大量有用的在线资源和缓动预设可以为缓动功能提供更多种类。

更受欢迎的在线资源包括 Andrey Sitnik 和 Ivan Solovev 的 Easing Functions Cheat Sheet 以及 Matthew Lein 的 CSS Easing Animation Tool。 这些工具提供了广泛的预设,您可以将其用作缓动功能的基础,然后微调曲线以适合您的动画时间线。

Easing Functions Cheat Sheet 包含 30 个有用的 Cubic Bezier 函数预设
Easing Functions Cheat Sheet 包含 30 个有用的功能预设。 (大预览)

动画和可访问性

通常在使用缓动函数和动画时,解决可访问性要求很重要。 有些人喜欢以减少动作浏览网页,所以我们应该提供适当的后备。 这可以通过广泛支持的偏好减少运动媒体查询轻松完成。 此媒体查询允许我们删除动画或根据用户偏好分配不同的动画。

 .animated-element { animation: /* Regular animation */; } @media (prefers-reduced-motion) { .animated-element { /* Accessible animation with reduced motion */ } }

我修改了 Alvaro Montoro 的模拟时钟示例,为设置了prefers-reduced-motion标志的用户提供了替代动画。

请参阅 Adrian Bece 的 Pen [CSS 模拟时钟,更喜欢减少运动](https://codepen.io/smashingmag/pen/QWdoXPN)。

请参阅 Adrian Bece 的 Pen CSS Analog Clock,它更喜欢减少运动。

在默认动画中,时钟的秒针不断移动,这可能会给某些用户带来困难。 通过将动画计时功能更改为steps ,我们可以轻松地使动画更易于访问。 在以下示例中,设置了prefers-reduced-motion标志的用户将显示一个动画,其中秒臂每五秒滴答一次。

 @media (prefers-reduced-motion) { .arm.second { animation-timing-function: steps(12); } }

结论

缓动函数或计时函数通过影响动画速率(速度)来改变动画的外观和感觉。 缓动功能使我们能够创建类似于自然运动的动画,从而改进、更令人愉悦的用户体验并给用户留下更好的印象。 我们已经了解了如何使用linearease-outease动等预定义值来快速添加计时函数,以及如何使用cubic-bezier函数创建自定义缓动函数以获得更令人印象深刻和有影响力的动画。 我们还介绍了可用于创建“滴答”动画但很少使用的楼梯函数。 在创建动画时,重要的是要牢记可访问性,并为设置了prefers-reduced-motion标志的用户提供一种替代的、较少分散注意力的动画和较少的运动。

有很多浏览器和在线工具可以简化和简化创建自定义缓动函数,因此创建具有优美流程的动画比以往任何时候都容易。 如果您还没有这样做,我建议您尝试各种缓动函数并创建自己的缓动函数库。

参考

  • <easing-function> , MDN 网络文档
  • “使用动画”,MDN 网络文档
  • “Safari 13.1 中的 Web 动画”,Antoine Quint,WebKit
  • “Easing 的基础”,Paul Lewis,Web Fundamentals,Google 开发者
  • “检查动画”,Kayce Basques,Chrome DevTools,Chrome 开发人员