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
,或在成功设置startTime
后,如果调用的结果是 播放状态 发生改变, 那么任何后续对 animation-play-state 的更改将不再导致CSSAnimation
被播放或暂停, 正如在 § 4.5 animation-play-state 属性 中定义的那样。对 暂停播放状态 的更改要求确保,即使在调用
reverse()
或设置startTime
后,动画仍然继续观察 animation-play-state 的更改。 -
在成功设置
effect
为null
或某个其他非原始AnimationEffect
后,任何后续对除了 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 的 拥有元素 不同,则按它们相应的 拥有元素 的 树顺序 排序。 对于伪元素,排序顺序如下:
-
元素
-
::marker
-
::before
-
其他未特别提及的伪元素,按构成每个选择器的 Unicode 代码点升序排序
-
::after
-
元素子项
-
-
否则,基于它们在(公共)animation-name 属性中的位置对 A 和 B 进行排序。
没有 拥有元素 的 CSS 动画的复合顺序基于它们在 全局动画列表 中的位置。
这与为过渡定义的行为不同。我们可能应该首先对过渡进行排序,然后是动画,然后使用全局动画列表。原因是当开发工具等保留孤立的动画和过渡以便重放时,它们应该大致保持相同的复合顺序。
使用本规范定义的标记生成的 CSS 动画在创建时 不会 添加到 全局动画列表。 相反,这些动画会在它们与 拥有元素 解除关联后首次从 空闲播放状态 转移时附加到 全局动画列表。 与其 拥有元素 解除关联但仍处于 空闲 的 CSS 动画没有定义的复合顺序。
注意,这种行为依赖于动画与其 拥有元素 解除关联总是会导致它进入(或保持)空闲播放状态。
3. 组装关键帧
3.1. 声明关键帧:@keyframes 规则
参见 CSS 动画 1 § 3 关键帧。
3.2. 处理关键帧
对于目标(伪)元素 element 上 animation-* 属性的 协调值列表 中定义的第 N 个动画效果,生成其关联的 关键帧,如下所示:
-
设置默认值:
-
令 default timing function 为 element 上 计算值 对应的 animation-timing-function。
-
令 default composite 为 element 上 计算值 对应的 animation-composition。
-
令 keyframes 为一个空的 关键帧 对象序列, 每个对象都包含 关键帧偏移、关键帧时序函数、关键帧合成 和 关键帧值。
-
令 animated properties 为 CSS 属性名称的空集。
-
-
收集声明的关键帧:
-
在文档顺序中找到最后一个 @keyframes 规则,其 <keyframes-name> 与对应的 animation-name 值 name 匹配。
如果没有与 name 匹配的 @keyframes 规则 (或 name 为 none), 则中止此过程。 在这种情况下,不生成动画,并取消任何与 name 匹配的现有动画。
-
将所有具有相同 指定的 <keyframe-selector> 的 关键帧块 分组(将 from 视为 0%,将 to 视为 100%), 最后声明的 animation-timing-function 的 计算值(如果没有这样的声明,则默认为 default timing function), 和最后声明的 animation-composition 的 计算值(如果没有这样的声明,则默认为 default composite)。
-
对于每组匹配的 关键帧块,按其排序顺序中的最早 关键帧块 排序:
-
-
生成初始和最终帧:
-
找到或创建 initial keyframe,一个具有 0% 关键帧偏移、默认时序函数 作为其 关键帧时序函数,默认合成 作为其 关键帧合成 的 关键帧。
-
对于 animated properties 中的任何属性,如果它不存在于偏移为 0% 的关键帧或 使用关键帧顺序 中较早的位置, 则将该属性在 element 上的 计算值 添加到 initial keyframe 的 关键帧值 中。
-
如果 initial keyframe 的 关键帧值 不是空的,则将 initial keyframe 添加到 keyframes 的开头。
-
对 final keyframe 重复此过程,使用 100% 偏移,考虑在 使用关键帧顺序 中较晚的位置,并将其附加到 keyframes 中。
-
-
排序帧:
-
指定顺序 是根据上述步骤得出的 keyframes 的顺序, 即文档顺序,重复的关键帧折叠到最早的位置。
-
计算顺序 是由
getKeyframes()
返回的顺序,按其 关键帧偏移 稳定排序。 -
使用顺序 是将 keyframes 附加到动画效果时间轴上后按从早到晚的顺序排列的顺序,按 计算顺序 打破平局。
本规范引入的任何关于排序计算关键帧的具体要求应集成到 Web 动画 § 5.3.3 计算计算的关键帧 中。 本规范引入的任何关于使用关键帧的具体要求应集成到 Web 动画 § 5.3.4 关键帧效果的效果值 中。 上述关键帧集之间区别的描述应移至信息性说明中。
注意:虽然 计算顺序 对具有 <百分比> 偏移的关键帧进行排序, 但它会保持 <时间线范围名称> 指定的关键帧按其 指定顺序,即使它们在 使用顺序 中排得更晚。
-
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 动画 Level 1 的描述更为一般,原因是它需要考虑通过 Web Animations API [WEB-ANIMATIONS] 进行动画搜索或反转的可能性。
CSS 动画事件的 目标 是动画的 拥有元素。如果没有 拥有元素,则不会分发任何 CSS
动画事件(尽管在相应的 CSSAnimation
对象上仍然分发 Web 动画中定义的 动画播放事件)。
为了确定要分发哪些事件,使用 Web Animations 模型中定义的阶段。这些定义适用于 动画效果,然而,为了分发事件,我们认为 CSS 动画与其 关联效果 处于相同的阶段。例如,如果 CSS 动画的 关联效果 处于 before 阶段,则该动画也处于 before 阶段。
没有 关联效果 的 CSS 动画,如果其 当前时间 是 未解析 的,则认为其处于 空闲阶段;如果当前时间小于零,则处于 before 阶段;否则处于 after 阶段。
同样地,随后提到的 开始延迟、活动时长、当前迭代、迭代开始 和 迭代时长,都应理解为指动画的 关联效果 的相应属性。
为了计算每个事件的 elapsedTime
,使用以下定义:
每次建立一个新的 动画帧 并且动画没有 待处理播放任务 或 待处理暂停任务 时,将通过比较动画在建立新 动画帧 之前和之后的阶段来确定要分发的事件:
变化 | 分发的事件 | 已消耗时间(毫秒) |
---|---|---|
空闲 或 之前 → 活动 | animationstart
| 间隔开始 |
空闲 或 之前 → 之后 ٭ | animationstart
| 间隔开始 |
animationend
| 间隔结束 | |
活动 → 之前 | animationend
| 间隔开始 |
活动 → 活动 且动画的当前迭代自上次动画帧以来已发生变化 | animationiteration
| (见下文) † |
活动 → 之后 | animationend
| 间隔结束 |
之后 → 活动 | animationstart
| 间隔结束 |
之后 → 之前 ٭ | animationstart
| 间隔结束 |
animationend
| 间隔开始 | |
非 空闲 且 非 之后 → 空闲 | animationcancel
| 动画取消时的活动时间,使用 填充模式计算。 |
٭ 当状态更改时列出多个事件时,所有事件都会按列出的顺序立即连续分发。
† 对于 animationiteration
事件,已消耗时间 的定义如下:
-
让 previous current iteration 为上一个动画帧的 当前迭代。
-
如果 previous current iteration 大于 当前迭代,则将 iteration boundary 设置为
当前迭代 + 1
,否则将其设置为 当前迭代。
由于上表和上述步骤中定义的 已消耗时间
以毫秒表示,必须将其除以1,000以生成以秒为单位的值,然后再将其赋值给 elapsedTime
的成员,AnimationEvent
。
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
接口。 - 描述了待处理样式更改的要求。