1. Delta 规范
这是一个 Delta 规范,意味着它目前只包含与 CSS 动画第 1 级 [CSS3-ANIMATIONS] 的差异。 一旦第 1 级规范更接近完成,它将与此处的补充合并为完整的第 2 级规范。
2. 动画
本规范中定义的任何动画属性的更改都会导致相应的 CSSAnimation
对象及其关联对象
根据这些属性与 § 3 组装关键帧 中定义的 Web 动画概念之间的对应关系进行更新。
但是,如果作者使用 Web 动画编程接口修改动画,则编程接口的更改优先,具体如下:
-
在成功调用
setKeyframes()之后,关联的KeyframeEffect和CSSAnimation,任何后续对匹配的 @keyframes 规则或目标元素的 animation-timing-function 属性的解析值的更改将不会反映在该动画中。但是,如果删除了最后一个匹配的 @keyframes 规则,动画必须仍然取消。
-
在成功调用
updateTiming()之后,关联的KeyframeEffect和CSSAnimation,对于包含在timing参数中的每个属性, 任何后续对相应动画属性的更改将不会反映在该动画中。例如,调用
cssAnimation.effect.updateTiming({ duration: 1000 })会导致忽略后续对 animation-duration 的更改,但 animation-delay 的更改仍会反映在KeyframeEffect的时序中。 -
在成功调用
play()或pause()之后,关联的CSSAnimation,任何后续对 animation-play-state 的更改将不再导致CSSAnimation被播放或暂停,正如在 § 4.5 animation-play-state 属性 中定义的那样。 -
在
reverse()成功调用于CSSAnimation后,或在CSSAnimation上成功设置startTime后, 如果由于该调用,CSSAnimation的播放状态变为或不再为暂停播放状态, 此后对 animation-play-state 的任何更改都将不再 使CSSAnimation播放或暂停 如 § 4.5 animation-play-state 属性中所定义。对 暂停播放状态 的更改要求确保,即使在调用
reverse()或设置startTime后,动画仍然继续观察 animation-play-state 的更改。 -
在成功设置
effect(属于CSSAnimation) 为null或某个AnimationEffect而非原始的KeyframeEffect后, 随后对除 animation-name 或 animation-play-state 以外的动画属性所做的所有更改都不会反映在 该动画中。 类似地,对匹配的 @keyframes 规则所做的任何更改也不会反映 在该动画中。 不过,如果最后一个匹配的 @keyframes 规则被移除, 该动画仍必须被取消。
注意,上面的规则中引用成功调用是必要的,以确保当这些方法中的任何一个抛出异常时,覆盖行为不会被应用。
2.1. 拥有元素
动画的 拥有元素 是指应用了生成动画的 animation-name 属性的元素或伪元素。
如果元素的 display 属性设置为 none,并且其 display 值在忽略过渡和动画的 层叠源 时会计算为 none, 则终止该 拥有元素 的正在运行的动画。 如果一个元素的 display 为 none,并且其 display 值在忽略过渡和动画的 层叠源 时计算为 none, 将 display 更新为非 none 的值将启动所有由 animation-name 属性应用于该元素的动画。
注意:实际上,这意味着除非样式在没有动画效果的情况下也计算为 none,否则动画到 display 值为 none 的情况不会终止正在运行的动画。
如果使用本规范定义的标记生成的动画后来通过更新 animation-name 属性的计算值与该动画的 拥有元素 解除关联,则动画将与其 拥有元素 解除关联(即,从那时起,它不再有 拥有元素)。
在下面的示例中,animation 的初始 拥有元素 是 elem。animation 通过更新
elem 的 animation-name 属性的计算值与 element 解除关联。
elem. style. animation= 'spin 1s' ; let animation= elem. getAnimations()[ 0 ]; // animation’s owning element is elem elem. style. animation= '' ; // animation no longer has an owning element
请注意,虽然 拥有元素 通常等于动画的 目标元素 及其 关联效果, 但这并不总是如此。 下面的示例演示了这些元素可能不同的一些情况。
elem. style. animation= 'move 1s' ; let animation= elem. getAnimations()[ 0 ]; // animation.effect.target == elem == animation’s owning element animation. effect. target= elem2; // animation.effect.target == elem2 != animation’s owning element animation. effect= null ; // animation.effect?.target is undefined != animation’s owning element
2.2. 动画复合顺序
由本规范中定义的标记生成的动画具有一个动画类‘CSS 动画’。
具有所属元素的 CSS 动画,其合成顺序比 CSS 过渡更晚,但比没有特定动画类的动画更早 。
在具有所属元素的 CSS 动画集合中,两个 动画 A 和 B 按如下方式以合成顺序(从前到 后)排序:
-
如果 A 和 B 的所属元素不同,则按照它们对应的所属元素的树顺序对 A 和 B 排序。 对于伪元素,排序顺序如下:
-
元素
-
::marker
-
::before
-
此列表中未明确提及的任何其他伪元素, 按构成各选择器的 Unicode 码点升序排序
-
::after
-
元素子节点
-
-
否则,根据(共同的)所属 元素的 animation-name 属性计算值中的位置,对 A 和 B 排序。
没有所属元素的 CSS 动画的合成顺序,基于它们在全局动画列表中的位置。
这与为过渡定义的行为不同。我们应该 可能先对过渡排序,然后对动画排序,再使用全局动画 列表。原因是,当开发者工具等保留孤立的 动画和过渡以便重放它们时,它们应保持 大致相同的合成顺序。
使用本规范中定义的标记生成的 CSS 动画在创建时不会被添加到全局动画列表中。 相反,这些动画会在 与其所属元素解除关联后首次离开空闲播放状态的时刻,被追加到全局动画列表。 已与其所属元素解除关联但仍处于空闲状态的 CSS 动画没有定义的 合成顺序。
注意,此行为依赖于这样一个事实:将动画 与其所属元素解除关联总会使其进入(或保持在)空闲播放状态。
3. 组装关键帧
3.1. 声明关键帧:@keyframes 规则
参见 CSS 动画 1 § 3 关键帧。
3.2. 处理关键帧
对于由第 N 项定义的每个动画效果 (该项位于目标(伪)元素 element 的 协调值列表中,该列表对应于此元素的 animation-* 属性), 其关联的 关键帧按如下方式生成:
-
设置默认值:
-
令 default timing function 为 element 上 animation-timing-function 对应的计算值。
-
令 default composite 为 element 上 animation-composition 对应的计算值。
-
令 keyframes 为一个由关键帧对象组成的空序列, 每个对象都具有 keyframe offset、keyframe timing function、keyframe composite 和 keyframe values。
-
令 animated properties 为一个 CSS 属性名的空集合。
-
-
收集已声明的关键帧:
-
按文档顺序查找最后一个 @keyframes at 规则, 其 <keyframes-name> 与 对应的 animation-name 值 name 匹配。
如果不存在 @keyframes at 规则 其 <keyframes-name> 与 name 匹配(或 name 为 none), 则中止此过程。 在这种情况下不会生成动画, 并取消任何与 name 匹配的现有动画。
-
将所有共享同一关键帧块归为一组,这些块具有相同的指定 <keyframe-selector>(将 from 视为 0%,将 to 视为 100%)、 最后声明的 animation-timing-function 计算值(如果没有这样的声明,则默认为 default timing function), 以及最后声明的 animation-composition 计算值(如果没有这样的声明,则默认为 default composite)。
-
对于每个这样的匹配关键帧块组, 按照其最早的关键帧块在排序顺序中的位置排列:
-
-
生成初始帧和最终帧:
-
查找或创建 initial keyframe, 即一个 keyframe offset 为 0%、以 default timing function 作为其 keyframe timing function 的关键帧, 并以 default composite 作为其 keyframe composite。
-
对于 animated properties 中既未以其他方式出现在偏移量为 0% 的 关键帧中,也未出现在按 已用关键帧顺序应排在更前位置的关键帧中的任何属性, 将该属性在 element 上的 计算值 添加到 initial keyframe 的 keyframe values 中。
-
如果 initial keyframe 的 keyframe values 不为空, 则将 initial keyframe 前置到 keyframes。
-
对 final keyframe 重复上述操作, 使用 100% 的偏移量, 考虑在使用的关键帧顺序中位置更晚的关键帧, 并将其追加到 keyframes。
-
-
对帧排序:
-
keyframes 的指定顺序是上述步骤产生的顺序, 即文档顺序,其中重复关键帧被合并 到最早的位置。
-
keyframes 的计算顺序——
即 getKeyframes()返回的顺序——通过将偏移量指定为 <percentage>、from 关键字或 to 关键字的任何关键帧 移到列表前部(位于生成的 initial keyframe 之后,如果存在), 并对这些关键帧执行稳定排序 按其 keyframe offset 排序而得。 -
keyframes 的使用顺序——
即用于插值并计算实际动画帧的顺序—— 通过将 keyframes 附加到动画效果的时间线上而得 假定迭代次数为 1 并按照从最早到最晚的顺序排列它们, 对于相同位置则使用计算关键帧顺序来打破平局。
本规范引入的关于排序计算关键帧的任何具体要求 都应整合到 Web 动画 § 5.3.3 计算已计算关键帧中。 本规范引入的关于使用关键帧的任何具体要求 都应整合到 Web 动画 § 5.3.4 关键帧效果的效果值中。 以上对这些关键帧集合之间区别的描述 应移至资料性注释中。
注:虽然计算关键帧顺序会对具有 <percentage> 偏移量的关键帧进行排序, 但它会将使用 <timeline-range-name> 指定的关键帧保持在其指定关键帧顺序中——
位于任何 <percentage> 关键帧之后 (生成的 final keyframe 除外), 即使这些关键帧在使用的关键帧顺序中出现得更晚。 -
4. 声明动画
CSS 动画通过使用 animation-* 属性将关键帧绑定到元素来定义 。 这些列表值属性, 全部都是 animation 简写属性的长写属性, 它们构成一个协调列表属性组,以 animation-name 作为协调列表基础属性,并由协调值列表中的每一项定义单个动画效果的属性。
参见 CSS Values 4 § A 协调列表值属性 以了解各个 animation-* 属性值如何协调。
4.1. animation-duration 属性
| 名称: | animation-duration |
|---|---|
| 值: | [ auto | <time [0s,∞]> ]# |
| 初始值: | auto |
| 应用于: | 所有元素 |
| 是否继承: | 否 |
| 百分比: | 不适用 |
| 计算值: | 列表,每项要么是时间,要么是关键字 auto |
| 规范顺序: | 根据语法 |
| 动画类型: | 不可动画 |
animation-duration 属性指定了动画的 迭代持续时间 及其关联的 动画效果。
- auto
-
对于时间驱动的动画,相当于 0s。
对于 滚动驱动的动画,相当于考虑了 animation-range、animation-delay 和 animation-iteration-count 的时间线所需的持续时间。 参见 滚动驱动动画 § 4.1 有限时间线计算。
- <time [0s,∞]>
-
对于时间驱动的动画,指定动画完成一个循环所需的时间。
负 <time> 是无效的。
如果 <time> 为 0s,如初始值,则动画的关键帧没有效果, 但动画本身仍会瞬时发生。 具体来说,开始和结束事件将被触发; 如果 animation-fill-mode 设置为 backwards 或 both, 动画的第一帧(由 animation-direction 定义)将在 animation-delay 期间显示。 在 animation-delay 之后,动画的最后一帧(由 animation-direction 定义)将在 animation-fill-mode 设置为 forwards 或 both 时显示。 如果 animation-fill-mode 设置为 none,则动画将没有可见效果。
4.2. animation-timing-function 属性
animation-timing-function 用于确定应用于每个 关键帧 的 时序函数,如 § 3 组装关键帧 中所定义。
4.3. animation-iteration-count 属性
animation-iteration-count 属性指定了动画的 迭代计数 及其关联的 动画效果。
4.4. animation-direction 属性
animation-direction 属性指定了动画的 播放方向 及其关联的 动画效果。
4.5. animation-play-state 属性
animation-play-state 用于暂停或播放动画。
如果在任何时间点,包括动画首次生成时,动画对应的 animation-play-state 的解析值是新的 running, 实现必须运行相关程序以 播放动画,并将 自动倒带标志 设置为 false。
如果在任何时间点,包括动画首次生成时,动画对应的 animation-play-state 的解析值是新的 paused, 实现必须运行相关程序以 暂停动画。
上述要求不适用于通过 Web 动画 API 覆盖动画播放状态的情况,如 § 2 动画 中所述。
4.6. animation-delay 属性
animation-delay 属性指定了动画的 启动延迟 及其关联的 动画效果。
4.7. animation-fill-mode 属性
animation-fill-mode 属性指定了动画的 填充模式 及其关联的 动画效果。
4.8. animation-composition 属性
animation-composition 属性定义了多个动画同时影响同一属性时使用的 合成操作。
| 名称: | animation-composition |
|---|---|
| 值: | <single-animation-composition># |
| 初始值: | replace |
| 应用于: | 所有元素 |
| 是否继承: | 否 |
| 百分比: | 不适用 |
| 计算值: | 列表,每项为指定的关键字 |
| 规范顺序: | 根据语法 |
| 动画类型: | 不可动画 |
<single-animation-composition> = replace | add | accumulate
animation-composition 的值具有 Web Animations 中为对应的 合成操作 定义的含义,详见 [WEB-ANIMATIONS]。
在关键帧中指定时,animation-composition 定义了每个属性在该关键帧中使用的合成操作,直到下一个指定每个属性的关键帧。
@keyframes heartbeat {
from {
scale: 1;
animation-timing-function: ease-out;
}
30% {
scale: 1.3;
}
}
.heartbeat {
animation: heartbeat 0.3s 2s infinite;
}
@keyframes throb {
50% {
scale: 1.8;
}
}
.icon:mouseover {
animation: throb 0.4s add;
}
如果将这两个动画应用于同一元素,通常只会应用一个动画,但通过在第二个动画中指定 add 作为 animation-composition,两个动画的结果将被合并。
由于 CSS 过渡 [CSS3-TRANSITIONS] 的合成顺序较低,可以使用 animation-composition 将 CSS 动画与底层的过渡效果结合,如以下示例所示。
.icon {
filter: blur(20px);
transition: filter 0.5s;
}
.icon:hover {
filter: blur(0px);
animation: brightness-pulse 3s infinite add;
}
@keyframes brightness-pulse {
0% {
scale: 1.1;
filter: brightness(130%);
}
10% {
scale: 1;
filter: brightness(100%);
}
}
4.9. animation-timeline 属性
animation-timeline 属性定义了用于动画的 时间轴。
注意: 此规范未引入指定动画时间轴的语法,而是由其他规范(例如滚动关联动画 [SCROLL-ANIMATIONS])来规定。
| 名称: | animation-timeline |
|---|---|
| 值: | <single-animation-timeline># |
| 初始值: | auto |
| 应用于: | 所有元素 |
| 是否继承: | 否 |
| 百分比: | 不适用 |
| 计算值: | 列表,每项为大小写敏感的 css 标识符 或关键字 none、auto。 |
| 规范顺序: | 按照语法 |
| 动画类型: | 不可动画 |
<single-animation-timeline> = auto | none | <custom-ident> | <scroll()> | <view()>
animation-timeline 属性与 animation-name 和 animation-duration 类似,可以有一个或多个值,每个值为元素上的相应 动画 提供附加行为,时间轴与动画的匹配如此处所述。
每个值的类型为 <single-animation-timeline>,其可能的值具有以下效果:
- auto
-
动画的 时间轴是
DocumentTimeline,更具体地说,是 默认文档时间轴。 - none
-
动画未与 时间轴关联。
- <custom-ident>
-
如果在此元素上有命名的 滚动进度时间轴 或 视图进度时间轴,则使用引用的时间轴,如 Scroll-driven Animations § 4.2 命名时间轴范围和查找 中定义的那样。
否则,动画未与 时间轴关联。
- <scroll()>
-
使用给定 scroll() 函数指示的 滚动进度时间轴。参见 Scroll-driven Animations § 2.2.1 滚动() 表示法。
- <view()>
-
使用给定 view() 函数指示的 视图进度时间轴。参见 Scroll-driven Animations § 3.3.1 视图() 表示法。
改进 animation-name 在 animation-timeline 未指定时用于选择时间轴的功能。允许使用 animation-name 选择时间轴,使大多数常见动画能够只使用一个名称同时为关键帧和时间轴提供服务,简化操作和提高可用性。animation-timeline 属性为作者提供了额外的控制权,可以在必要时独立选择关键帧和时间轴。
当多个 animation-* 属性同时设置时,首先更新 animation-timeline,因此例如对 animation-play-state 的更改适用于 animation-timeline 中同时应用的时间轴。
4.10. animation 简写属性
animation 简写属性的语法如下:
<single-animation> = <'animation-duration'> || <easing-function> || <'animation-delay'> || <single-animation-iteration-count> || <single-animation-direction> || <single-animation-fill-mode> || <single-animation-play-state> || [ none | <keyframes-name> ] || <single-animation-timeline>
5. 动画事件
5.1. 事件分发
注,这是对事件分派比 CSS 动画第 1 级 [CSS3-ANIMATIONS] 中更通用的描述,因为它必须考虑 使用 Web 动画 API [WEB-ANIMATIONS] 对动画进行寻位或反转的可能性。
CSS 动画事件的目标是
动画的所属元素。
如果没有所属元素,则不会分派 CSS 动画事件
(尽管 Web 动画中定义的动画播放事件仍然
会在相应的 CSSAnimation
对象上分派)。
为了确定要分派哪些事件,使用 Web 动画模型中定义的阶段。这些定义适用于动画 效果,但是,为了分派事件,我们认为 CSS 动画与其关联效果具有相同的阶段。 例如,如果 CSS 动画的关联效果处于之前阶段,则该 CSS 动画处于之前阶段。
没有关联效果的 CSS 动画,如果其当前时间为未解析,则认为其处于空闲阶段;如果其当前时间小于零,则处于之前阶段, 否则处于之后阶段。
类似地,后续对 CSS 动画的开始延迟、活动 持续时间、当前迭代、迭代开始和迭代持续时间的引用应理解为 指动画的关联效果的相应属性。
为了计算每个事件的 elapsedTime,使用以下
定义:
每当建立一个新的动画帧且动画没有待处理播放任务或待处理暂停任务时, 要分派的事件通过 如下比较建立新动画帧前后动画的阶段来确定:
| 变化 | 分派的事件 | 经过时间 (ms) |
|---|---|---|
| 空闲或之前 → 活动 | animationstart
| 区间开始 |
| 空闲或之前 → 之后 ٭ | animationstart
| 区间开始 |
animationend
| 区间结束 | |
| 活动 → 之前 | animationend
| 区间开始 |
| 活动 → 活动 且动画的关联效果的当前迭代自上一个动画帧以来已更改 | animationiteration
| (见下文)† |
| 活动 → 之后 | animationend
| 区间结束 |
| 之后 → 活动 | animationstart
| 区间结束 |
| 之后 → 之前 ٭ | animationstart
| 区间结束 |
animationend
| 区间开始 | |
| 非空闲且非之后 → 空闲 | animationcancel
| 动画在被取消时刻的活动时间 使用 both 的填充模式计算。 |
٭ 当针对 一次状态变化列出多个事件时,所有事件均按所列顺序并立即 连续分派。
† animationiteration
事件的经过时间
定义如下:
-
令 previous current iteration 为上一个动画帧的当前迭代。
-
如果 previous current iteration 大于当前 迭代,令 iteration boundary 为
当前 迭代 + 1,否则令其为当前迭代。
由于上表和过程中定义的经过时间以
毫秒表示,因此在将其赋值给
AnimationEvent
的 elapsedTime
成员之前,必须除以 1,000 以生成以秒为单位的值。
6. DOM 接口
6.1. CSSAnimation 接口
[Exposed =Window ]interface :CSSAnimation Animation {readonly attribute CSSOMString animationName ; };
animationName, 类型为 CSSOMString,只读-
用于查找匹配关键帧规则的键,这些规则定义动画创建时的关联效果。 这是导致此 对象生成的 animation-name 属性的值。
6.2. 待定样式更改的要求
各种操作可能会影响元素上属性的计算值。用户代理可以作为一种优化手段,将重新计算这些值的操作推迟到必要时再进行。然而,所有在此规范中定义的编程接口中包含的操作,以及 Web Animations 中定义的那些操作[WEB-ANIMATIONS],如果可能返回对象或由此规范定义的动画状态,则必须确保其结果与完全处理这些待定的计算值更改一致。
elem 的指定样式最初更新时,用户代理可能会推迟重新计算 animation 属性的计算值。
然而,getAnimations()
方法在 elem 上被调用时,根据 Web Animations 的定义,可以返回 CSSAnimation
对象,如本规范定义。因此,根据本节的要求,用户代理必须在返回结果之前计算 elem 的animation 属性的更新值并创建请求的 CSSAnimation
对象。
同样,读取 playState
可能也取决于待处理的样式更改。
7. 隐私考虑
本规范尚未报告任何隐私问题。
8. 安全考虑
本规范尚未报告任何安全问题。
9. 变更
9.1. 近期变更
自 2023 年 3 月 2 日工作草案 以来的变更包括:
- 将 auto 添加为 初始值,应用于 animation-duration。(Issue 6530)
- 重写了 § 3.2 关键帧处理,重新使用了 级联,处理非百分比的关键帧偏移,处理超出 [0,1] 范围的关键帧偏移,并使用 animation-composition 作为默认的组合方式。
- 减少了 display: none 取消动画的情况。( Issue 6429)
- 交叉链接到 CSS Values 4 § A 协调列表值属性,定义各个 animation-* 属性如何交互。
- 澄清了动画属性中的 animation-timeline 是首先应用的。
9.2. 自 CSS Animations, Level 1 以来的变更
- 定义了 CSS 动画与 Web 动画之间的交互,并引入了拥有元素和动画合成顺序的概念。
- 详细描述了关键帧对象的生成。
- 引入了 animation-composition 属性,该属性定义了在多个动画同时影响同一属性时使用的合成操作。
- 引入了 animation-timeline 属性,用于定义与动画一起使用的时间线。
- 更新了 animation 速记属性,以考虑这些新属性。
- 描述了动画事件的分派。
- 添加了
CSSAnimation接口。 - 描述了待处理样式更改的要求。