1. 引言
本节不是规范性内容。
通常希望控制某些值变化的速率。例如,逐渐增加元素移动的速度可以赋予该元素一种重量感,使其在积聚动能时表现得更加真实。这可以用于制作直观的用户界面元素或令人信服的卡通道具,使其表现得像物理对象一样。另一方面,有时希望动画以不同的步骤前进,例如一个分段的轮子旋转,使得段始终出现在相同的位置。
同样,控制梯度插值的变化速率可以用于产生不同的视觉效果,例如暗示凹面或凸面,或产生条纹效果。
缓动函数 提供了一种通过接受输入进度值并生成相应的输出进度值来转换这些值的方法。
给定输入进度为0.7,缓动函数缩放该值以产生输出进度0.52。
将此缓动函数应用于动画将导致动画最初进展较慢,但随后逐渐加快。
1.1. 值定义
本规范使用值定义语法来自[CSS-VALUES-3]。未在本规范中定义的值类型在CSS值与单位[CSS-VALUES-3]中定义。与其他CSS模块的组合可能会扩展这些值类型的定义。
2. 缓动函数
缓动函数 必须是一个纯函数,这意味着对于给定的一组输入,它总是生成相同的 输出进度值。
输入进度值 是一个范围为 [-∞, ∞] 的实数。通常,输入进度值 在 [0, 1] 的范围内,但当 缓动函数 被链式调用时,这种情况可能不适用。
当缓动函数链式调用时,出现此类情况。例如,在 Web 动画中,缓动函数指定的输出可能成为关键帧效果中某个关键帧上的缓动函数的输入。在这种情况下,关键帧效果上的缓动函数输入可能超出 [0, 1] 范围。
输出进度值 是一个范围为 [-∞, ∞] 的实数。
某些类型的缓动函数还接受一个额外的布尔 before 标志 输入,这将在后续内容中定义。
本规范定义了四种类型的缓动函数,其定义如下。
指定 缓动函数 的语法如下:
测试
2.1. 线性缓动函数:linear()
线性缓动函数 具有 点,它是一个 列表 的 线性缓动点。最初是一个新的空列表。
线性缓动点 是一个 结构,具有以下内容:
- 输入
-
一个数字或 null
注意: 在 创建线性缓动函数 期间,这只有在为空时才为 null。
- 输出
-
一个数字
2.1.1. 语法
线性缓动函数 的语法如下:
<linear-easing-function> = linear(<linear-stop-list>) <linear-stop-list> = [ <linear-stop> ]# <linear-stop> = <number> && <linear-stop-length>? <linear-stop-length> = <percentage>{1,2}
linear() 通过调用 线性缓动函数 并传入其 <linear-stop-list>,作为 列表 的 <linear-stop> 解析为一个线性缓动函数。
2.1.2. 解析
要 创建线性缓动函数,给定一个 列表 的 <linear-stop> stopList, 执行以下操作。 它返回一个 线性缓动函数 或 失败。
-
令 function 为一个新的 线性缓动函数。
-
令 largestInput 为负无穷大。
-
如果 stopList 中的项少于两个,则返回 失败。
-
对于每个 stop 在 stopList 中:
-
如果 stop 具有 <linear-stop-length>,则:
-
将 point 的 输入 设置为以下两个值中的较大者:stop 的 <linear-stop-length> 的第一个 <percentage> 作为数字,或 largestInput。
-
将 largestInput 设置为 point 的 输入。
-
如果 stop 的 <linear-stop-length> 有第二个 <percentage>,则:
-
将 extraPoint 的 输入 设置为以下两个值中的较大者:stop 的 <linear-stop-length> 的第二个 <percentage> 作为数字,或 largestInput。
-
将 largestInput 设置为 extraPoint 的 输入。
-
-
否则,如果 stop 是 stopList 中的第一个 项,则:
-
将 point 的 输入 设置为 0。
-
将 largestInput 设置为 0。
-
-
否则,如果 stop 是 stopList 中的最后一个 项, 则将 point 的 输入 设置为以下两个值中的较大者:1 或 largestInput。
-
返回 function。
2.1.3. 序列化
例如:
-
linear(0, 0.25, 1) 序列化为 linear(0 0%, 0.25 50%, 1 100%)
-
linear(0 20%, 0.5 10%, 1) 序列化为 linear(0 20%, 0.5 20%, 1 100%)
-
linear(0, 0.25 25% 75%, 1) 序列化为 linear(0 0%, 0.25 25%, 0.25 75%, 1 100%)
要获取 线性缓动函数 (linearEasingFunction) 的 序列化计算值,执行以下操作。 它返回一个 字符串。
2.1.4. 线性缓动函数的输出
要 计算线性缓动输出进度,给定一个 线性缓动函数 linearEasingFunction,以及一个 输入进度值 inputProgress,执行以下操作。 它返回一个 输出进度值。
-
令 points 为 linearEasingFunction 的 点。
-
令 pointAIndex 为 points 中最后一个具有 输入 小于或等于 inputProgress 的 项的索引, 如果没有匹配项,则为 0。
-
如果 pointAIndex 等于 points 的 大小 减去 1,则将 pointAIndex 减 1。
注意: 这确保我们有下一个 点 进行比较。
-
令 pointA 为 points[pointAIndex]。
-
令 pointB 为 points[pointAIndex + 1]。
-
令 progressFromPointA 为 inputProgress 减去 pointA 的 输入。
-
令 pointInputRange 为 pointB 的 输入 减去 pointA 的 输入。
-
令 progressBetweenPoints 为 progressFromPointA 除以 pointInputRange。
-
令 pointOutputRange 为 pointB 的 输出 减去 pointA 的 输出。
-
令 outputFromLastPoint 为 progressBetweenPoints 乘以 pointOutputRange。
-
返回 pointA 的 输出 加上 outputFromLastPoint。
2.1.5. 示例
例如,linear(0, 0.25 75%, 1) 生成以下缓动函数,该函数在 75% 的时间内从 0 过渡到 .25, 然后在最后 25% 的时间内从 .25 过渡到 1:
例如,linear(0, 0.25 25% 75%, 1) 等效于 linear(0, 0.25 25%, 0.25 75%, 1), 生成以下缓动函数:
例如,以下是如何使用 linear() 创建可重复使用的“弹跳”缓动函数:
:root{ --bounce : linear ( /* 从开始到第一个弹跳 */ 0 , 0.063 , 0.25 , 0.563 , 1 36.4 % , /* 从第一个到第二个弹跳 */ 0.812 , 0.75 , 0.813 , 1 72.7 % , /* 从第二个到第三个弹跳 */ 0.953 , 0.938 , 0.953 , 1 90.9 % , /* 从第三个弹跳到结束 */ 0.984 , 1 100 % 100 % ); } .example{ animation-timing-function : var ( --bounce); }
定义以 1 100% 100%
结束,以创建两个最终点,
因此大于 1 的输入始终输出 1。
可以使用更多的点来创建更平滑的结果, 这在较慢的动画中可能是必需的。
2.2. 线性缓动关键字:linear
linear 关键字 生成一个恒等的 线性缓动函数,其 输出进度值 对所有输入均等于 输入进度值。
这与 linear(0, 1) 生成相同的结果。
注意: 虽然这会生成一个 线性缓动函数, 但关键字 linear 总是按原样序列化为 linear。 而等效的函数 linear(0, 1) 会序列化为 linear(0 0%, 1 100%)。 这些规则在 序列化 部分有说明。
2.3. 三次贝塞尔缓动函数:ease、ease-in、ease-out、ease-in-out、cubic-bezier()
三次贝塞尔缓动函数 是一种 缓动函数, 由四个实数定义, 这些实数指定了三次贝塞尔曲线的两个控制点 P1 和 P2,其端点 P0 和 P3 分别固定在 (0, 0) 和 (1, 1)。 P1 和 P2 的 x 坐标限制在 [0, 1] 范围内。
曲线的形状由控制点 P1 和 P2 的位置确定。
输入进度值作为曲线的 x 值, 而 y 值则为输出进度值。
三次贝塞尔缓动函数 具有以下语法 (使用 [CSS-VALUES-3] 中的符号表示):
每个值的含义如下:
- ease
-
等效于 cubic-bezier(0.25, 0.1, 0.25, 1)。
- ease-in
-
等效于 cubic-bezier(0.42, 0, 1, 1)。
- ease-out
-
等效于 cubic-bezier(0, 0, 0.58, 1)。
- ease-in-out
-
等效于 cubic-bezier(0.42, 0, 0.58, 1)。
-
- cubic-bezier(<number [0,1]>, <number>, <number [0,1]>, <number>)
-
指定了一个 三次贝塞尔缓动函数。 这四个数字指定了曲线的点 P1 和 P2,表示为 (x1, y1, x2, y2)。 两个 x 值必须在 [0, 1] 范围内,否则定义无效。
上面列出的关键字值如下图所示。
2.3.1. 三次贝塞尔缓动函数的输出
从输入进度映射到输出进度是通过确定给定 x 值(输入进度值)的对应 y 值(输出进度值)来实现的。 对该曲线的评估在许多来源中都有介绍,例如 [FUND-COMP-GRAPHICS]。
对于超出 [0, 1] 范围的 输入进度值,曲线会根据最近端点的切线无限延伸,如下所示:
2.4. 阶跃缓动函数:step-start、step-end、steps()
阶跃缓动函数 是一种 缓动函数,它将输入时间分成指定数量的等长区间。 该函数由若干 阶跃 和一个 阶跃位置 定义。 它的语法如下:
<阶跃位置> = jump-start | jump-end | jump-none | jump-both | start | end
每个值的含义如下:
- step-start
-
计算为 steps(1, start)
- step-end
-
计算为 steps(1, end)
阶跃缓动函数关键字值示例。 - steps(<整数>, <阶跃位置>?)
-
第一个参数指定函数中的间隔数量。 它必须是大于 0 的正整数, 除非第二个参数为 jump-none,此时它必须是大于 1 的正整数。
第二个参数是可选的,使用以下值之一来指定 阶跃位置:
- jump-start
-
第一次跃升发生在 输入进度值为 0 时。
- jump-end
-
最后一次跃升发生在 输入进度值为 1 时。
- jump-none
-
所有跃升发生在 (0, 1) 范围内。
- jump-both
-
第一次跃升发生在 输入进度值为 0 时, 最后一次跃升发生在 输入进度值为 1 时。
- start
-
表现如 jump-start。
- end
-
表现如 jump-end。
如果省略第二个参数,则默认值为 end。
这些值的示例如下:
阶跃缓动函数示例。
2.4.1. 阶跃缓动函数的输出
在阶跃发生的确切点,函数的结果在概念上是阶跃的顶端。然而,如果传递的输入中附带了 前标志 并为 true,则函数结果将在阶跃点对应阶跃的底端。
以下是 前标志 如何影响该函数行为的示例, 假设动画使用一个 阶跃缓动函数,其 阶跃位置 为 start,并且具有正延迟和向后填充。
例如,使用 CSS 动画:
animation : moveRight5 s 1 s steps ( 5 , start);
在延迟阶段,输入进度值将为零,但如果设置了 前标志 表明动画尚未达到其动画区间, 则缓动函数将输出零作为其 输出进度值,即第一个阶跃的底部。
为了计算 输出进度值,阶跃位置 start 被视为等同于 jump-start。 同样,end 被视为等同于 jump-end。 因此,以下算法不会明确提及 start 或 end。
注意:用户代理仍然必须区分 jump-start 和 start,以便进行序列化(参见 § 2.5 序列化)。
-
如果 阶跃位置 属性是以下之一:
将 当前阶跃 加 1。
-
如果 同时 满足以下两个条件:
将 当前阶跃 减 1。
-
如果 输入 进度值 ≥ 0 且 当前阶跃 < 0, 令 当前阶跃 为零。
-
根据 阶跃位置 计算 跃升数,如下所示:
-
如果 输入 进度值 ≤ 1 且 当前阶跃 > 跃升数,则将 当前阶跃 设为 跃升数。
-
输出进度值为
当前阶跃 / 跃升数
。
2.5. 序列化
缓动函数按照 [CSSOM] 中定义的通用序列化模式进行序列化,并具有以下附加要求:
-
关键字值 ease、linear、ease-in、ease-out 和 ease-in-out 按原样序列化, 也就是说,它们在序列化之前不会转换为等效的 cubic-bezier() 或 linear() 函数。
-
无论阶跃缓动函数是通过 steps() 函数,还是通过 step-start 或 step-end 关键字指定,序列化时按照以下规则:
-
如果 阶跃位置 为 jump-end 或 end, 则按 steps(<integer>) 进行序列化。
-
否则,按 steps(<integer>, <step-position>) 进行序列化。
-
隐私考虑
在本规范中尚未报告任何新的隐私问题。
本规范不会直接为 Web 平台引入任何新功能,而是提供其他规范可能引用的通用定义。
安全考虑
引用本规范中定义的功能的规范应考虑到,尽管缓动函数通常会接受范围为 [0,1] 的 输入进度值, 并生成范围为 [0,1] 的 输出进度值, 但情况并非总是如此。 缓动函数的应用应定义超出该范围的输入和输出的行为, 以确保它们不会引入新的安全问题。
3. 更改
3.1. 自第 1 级以来的新增内容
-
添加了 linear() 函数。
4. 致谢
本规范基于由 L. David Baron、Dean Jackson、David Hyatt 和 Chris Marrin 编辑的 CSS 过渡 规范。 编辑们还要感谢 Douglas Stockwell、Steve Block、Tab Atkins、Rachel Nabors、Martin Pitt,以及 Animation at Work slack 社区提供的反馈和贡献。