1. 简介
本节是非规范性的。
本规范引入了一个 DOM API 和相关的 CSS 功能, 使开发者可以创建称为 视图过渡 的动画视觉过渡, 用于不同 文档 状态之间的切换。
1.1. 将视觉过渡与 DOM 更新分离
传统上,在两个文档状态之间创建视觉过渡需要一个阶段,在该阶段两个状态同时存在于 DOM 中。 实际上,通常需要创建一个特定的 DOM 结构来表示这两个状态。 例如,如果一个元素在容器之间“移动”,则该元素通常需要在过渡期间存在于两个容器之外, 以避免被任一容器或它们的祖先元素裁剪。
这种额外的中间状态常常导致用户体验和可访问性问题,因为 DOM 的结构被纯粹的视觉效果所破坏。
视图过渡避免了这种麻烦的中间状态, 通过允许 DOM 即时切换状态, 然后在另一个层次上执行两种状态之间的可定制视觉过渡, 使用旧状态的静态视觉捕获和新状态的实时捕获。 这些捕获表示为 伪元素 的树(详细信息见 § 3.2 视图过渡伪元素), 其中旧的视觉状态与新的状态共存,允许如淡入淡出等效果, 同时从旧的大小和位置动画到新的大小和位置。
1.2. 视图过渡定制化
默认情况下,
document.
创建一个页面范围内的淡入淡出过渡,
在两个 DOM 状态之间。
开发者也可以选择独立捕获某些元素,
使用 view-transition-name CSS 属性,
使这些元素可以独立于页面的其他部分进行动画。
由于过渡状态(旧的和新的视觉捕获同时存在)表示为伪元素,
开发者可以使用诸如 CSS 动画 和 Web 动画 等熟悉的功能来自定义每个过渡。
startViewTransition()
1.3. 视图过渡生命周期
成功的 视图过渡 经过以下阶段:
-
开发者调用
document.
, 该方法返回一个startViewTransition
(updateCallback
)ViewTransition
对象 viewTransition。 -
当前状态被捕获为“旧”状态。
-
渲染被暂停。
-
开发者提供的
updateCallback
回调函数(如果有)被调用,从而更新文档状态。 -
viewTransition.
得到 fulfill。updateCallbackDone
-
当前状态被捕获为“新”状态。
-
创建过渡伪元素。参见 § 3.2 视图过渡伪元素 了解该结构概述。
-
渲染恢复,显示过渡伪元素。
-
viewTransition.
得到 fulfill。ready
-
伪元素持续动画直至结束。
-
移除过渡伪元素。
-
viewTransition.
得到 fulfill。finished
1.4. 过渡作为增强功能
视图过渡 API 设计的一个关键部分
是动画过渡是对底层文档状态变化的视觉增强。
这意味着,即使由于配置错误或设备限制导致无法创建视觉过渡,
也不会阻止开发者的 UpdateCallback
被调用,
即使事先已知过渡动画无法发生。
例如,如果开发者在 视图过渡生命周期 开始时调用 skipTransition()
,
则与动画过渡相关的步骤,
如创建 视图过渡树,
将不会发生。
然而,UpdateCallback
仍然会被调用。
仅跳过了视觉过渡,而不是底层的状态变化。
注意:如果还希望跳过 DOM 更改,则需要通过其他功能来处理。
是开发者可以用来处理此情况的一个功能示例。
navigateEvent
.signal
尽管视图过渡 API 允许通过 UpdateCallback
使 DOM 更改异步进行,
该 API 并不负责排队或以其他方式调度 DOM 更改,
除了任何过渡本身所需的调度外。
一些异步 DOM 更改可以同时发生(例如,它们发生在独立的组件中),
而另一些则需要排队或中止先前的更改。
最好将这些留给对应用程序有更全面了解的功能或框架来处理。
1.5. 渲染模型
视图过渡通过使用用户代理生成的伪元素来复制元素的渲染状态。 应用于元素自身或其后代的渲染方面, 例如视觉效果如 filter 或 opacity, 以及来自 overflow 或 clip-path 的裁剪, 在 捕获图像 时应用。
然而,诸如 mix-blend-mode 之类定义了元素嵌入时如何绘制的属性,无法应用于其图像。 这些属性被应用于元素的对应 ::view-transition-group() 伪元素, 该伪元素旨在生成一个等同于元素的盒子。
如果 ::view-transition-group() 在“新”状态中有对应的元素, 浏览器将保持复制到 ::view-transition-group() 的属性与“新”状态的 DOM 元素同步。 如果 ::view-transition-group() 在“旧”状态和“新”状态中都有对应, 并且被复制的属性是可插值的, 浏览器还会设置一个默认动画来平滑地对该属性进行动画处理。
1.6. 示例
function spaNavigate( data) { updateTheDOMSomehow( data); }
可以如下为其添加视图过渡(view transition):
function spaNavigate( data) { // 针对不支持该 API 的浏览器的降级处理: if ( ! document. startViewTransition) { updateTheDOMSomehow( data); return ; } // 带有过渡效果: document. startViewTransition(() => updateTheDOMSomehow( data)); }
这样会产生默认的快速渐变过渡效果:
渐变过渡是通过 CSS 动画作用在伪元素树上实现的,因此可以使用 CSS 进行自定义。例如:
::view-transition-old ( root), ::view-transition-new ( root) { animation-duration : 5 s ; }
这会使过渡变得更慢:
@keyframes fade-in{ from{ opacity : 0 ; } } @keyframes fade-out{ to{ opacity : 0 ; } } @keyframes slide-from-right{ from{ transform : translateX ( 30 px ); } } @keyframes slide-to-left{ to{ transform : translateX ( -30 px ); } } ::view-transition-old ( root) { animation : 90 ms cubic-bezier ( 0.4 , 0 , 1 , 1 ) both fade-out, 300 ms cubic-bezier ( 0.4 , 0 , 0.2 , 1 ) both slide-to-left; } ::view-transition-new ( root) { animation : 210 ms cubic-bezier ( 0 , 0 , 0.2 , 1 ) 90 ms both fade-in, 300 ms cubic-bezier ( 0.4 , 0 , 0.2 , 1 ) both slide-from-right; }
这是效果:
.main-header{ view-transition-name : main-header; } .main-header-text{ view-transition-name : main-header-text; /* 为元素赋予一致的大小,假设文本相同:*/ width: fit-content; }
默认情况下,这些组将从“旧”状态过渡到“新”状态时改变大小和位置,同时视觉状态进行交叉淡化:
在这种情况下,如果“旧”和“新”状态中都有侧边栏,静态展示会更好。否则,它应该以动画形式进入或退出。
:only-child伪类可以专门为这些状态创建动画:
.sidebar{ view-transition-name : sidebar; } @keyframes slide-to-right{ to{ transform : translateX ( 30 px ); } } /* Entry transition */ ::view-transition-new ( sidebar) :only-child{ animation : 300 ms cubic-bezier ( 0 , 0 , 0.2 , 1 ) both fade-in, 300 ms cubic-bezier ( 0.4 , 0 , 0.2 , 1 ) both slide-from-right; } /* Exit transition */ ::view-transition-old ( sidebar) :only-child{ animation : 150 ms cubic-bezier ( 0.4 , 0 , 1 , 1 ) both fade-out, 300 ms cubic-bezier ( 0.4 , 0 , 0.2 , 1 ) both slide-to-right; }
For cases where the sidebar has both an “old” and “new” state, the default animation is correct.
首先,在 CSS 中允许“旧”和“新”状态叠加在一起而不进行默认的混合,防止默认的交叉淡化动画:
// 存储上一次点击事件 let lastClick; addEventListener( 'click' , event=> ( lastClick= event)); function spaNavigate( data) { // 针对不支持该 API 的浏览器的降级处理: if ( ! document. startViewTransition) { updateTheDOMSomehow( data); return ; } // 获取点击位置,若无则取屏幕中心 const x= lastClick? . clientX?? innerWidth/ 2 ; const y= lastClick? . clientY?? innerHeight/ 2 ; // 计算到最远角的距离 const endRadius= Math. hypot( Math. max( x, innerWidth- x), Math. max( y, innerHeight- y) ); // 创建视图过渡: const transition= document. startViewTransition(() => { updateTheDOMSomehow( data); }); // 等待伪元素创建完毕: transition. ready. then(() => { // 动画 root 的新视图 document. documentElement. animate( { clipPath: [ `circle(0 at ${ x} px ${ y} px)` , `circle( ${ endRadius} px at ${ x} px ${ y} px)` , ], }, { duration: 500 , easing: 'ease-in' , // 指定要动画的伪元素 pseudoElement: '::view-transition-new(root)' , } ); }); }
结果如下:
2. CSS 属性
2.1. 为独立过渡的子树标记:view-transition-name 属性
名称: | view-transition-name |
---|---|
值: | none | <custom-ident> |
初始值: | none |
适用于: | 所有元素 |
是否继承: | no |
百分比: | n/a |
计算值: | 按指定 |
规范顺序: | 符合语法 |
动画类型: | 离散 |
注意:虽然 view-transition-name 是离散可动画(discretely animatable)的, 但对其进行动画并不会影响正在运行的视图过渡(view transition)。相反,这是一种可以随时间或基于时间线(timeline)变化的方式来设置其值的手段。 一个使用场景示例是根据滚动驱动动画(scroll-driven animations)来更改 view-transition-name。
view-transition-name 属性用于将元素“标记”为在视图过渡中捕获,并在指定的视图过渡名称(view transition name)下,于视图过渡树(view transition tree)中独立跟踪。被这样捕获的元素会独立于页面其他部分进行动画。
- none
-
元素不会以独立方式参与视图过渡。
- <custom-ident>
-
元素将以独立方式参与视图过渡——作为“旧”或“新”元素——并使用指定的视图过渡名称。
这里的 none 和 auto 两个值不属于 <custom-ident> 的范畴。
注意:如果此名称不是唯一的(即有两个元素同时指定了相同的 view transition name),那么该视图过渡将会中止。
注意:对于此 API, 如果某元素在旧状态下具有 view transition name foo, 而另一个元素在新状态下也具有 view transition name foo, 它们会被视为同一元素的不同可视状态,并在视图过渡树中配对。虽然这些元素本身未必指向同一对象,但将其视为同一概念页面实体的不同视觉状态是有用的模型。
如果元素的主盒(principal box)被分片(fragmented)、跳过内容(skipped), 或未渲染(not rendered),则该属性不会生效。 具体细节参见 § 7 算法。
2.1.1. 渲染合并
元素在视图过渡期间被捕获, 或者其 view-transition-name 的 计算值不是 none(在任何时间):
3. 伪元素
3.1. 伪元素树
注意:这是伪元素树的通用定义。如果其他特性需要此行为,这些定义将移至 [css-pseudo-4]。
伪元素根是一种 树状伪元素, 它是树中的 根, 这种树被称为伪元素树。
当一个伪元素 参与 一个伪元素树时, 它的原始伪元素是它的 父元素。
如果伪元素根 的一个后代 pseudo 没有其他兄弟元素, 那么:only-child 匹配该 pseudo。
注意:这意味着
::view-transition-new(ident):only-child
仅在父元素 ::view-transition-image-pair(ident)
中
包含一个子元素时选择它。
也就是说,没有其他兄弟元素
::view-transition-old(ident)
。
3.2. 视图过渡伪元素
视图过渡的可视化表示为一个称为 伪元素树的结构, 称为视图过渡树, 由下面定义的视图过渡伪元素组成。 这个树在设置过渡伪元素步骤期间构建, 并在从::view-transition伪元素 起源 于根元素。 所有的视图过渡伪元素都是从它们的 最终起源元素中选取, 即文档元素。
视图过渡树(view transition tree)不会暴露给可访问性树(accessibility tree)。
::view-transition ├─ ::view-transition-group(name) │ └─ ::view-transition-image-pair(name) │ ├─ ::view-transition-old(name) │ └─ ::view-transition-new(name) └─ …其他组…
每个带有 view-transition-name 的元素都会被单独捕获,并且每个唯一的 view-transition-name 都会生成一个 ::view-transition-group()。
为了方便起见,文档元素(document element) 在 用户代理样式表(user-agent style sheet) 中被赋予 view-transition-name 值为 "root"。
如果某次捕获没有“旧”或“新”状态,则 ::view-transition-old() 或 ::view-transition-new() 会缺失。
生成的每个伪元素都可以通过 CSS 进行定向,从而自定义其外观、行为和/或添加动画。这使得过渡效果可以实现完全的自定义。
3.2.1. 命名视图过渡伪元素
一些视图过渡伪元素 是命名视图过渡伪元素, 它们是函数式 树状 视图过渡伪元素,与视图过渡名称相关联。 这些伪元素以<pt-name-selector>作为参数, 其语法遵循以下模式:
::view-transition-pseudo(<pt-name-selector>)
其中<pt-name-selector>选择一个 视图过渡名称, 其语法定义如下:
<pt-name-selector> = '*' | <custom-ident>
命名视图过渡伪元素 选择器仅在其 <pt-name-selector> 匹配相应的伪元素的 伪元素的视图过渡名称时匹配, 也就是说,如果它是*或匹配的 <custom-ident>。
注意: 视图过渡伪元素的 视图过渡名称设置为触发其创建的 view-transition-name。
命名视图过渡伪元素 选择器的 <custom-ident>参数 的优先级等同于类型选择器。 命名视图过渡伪元素选择器带有 *参数的优先级为零。
3.2.2. 视图过渡树根:::view-transition伪元素
::view-transition 伪元素 是一个树状伪元素, 同时也是一个伪元素根。 它的起源元素 是文档的文档元素, 它的包含块 是快照包含块。
注意:这个元素作为所有::view-transition-group()伪元素的父元素。
3.2.3. 视图过渡命名子树根:::view-transition-group()伪元素
::view-transition-group() 伪元素 是一个命名视图过渡伪元素, 表示匹配的命名视图过渡捕获。 每个视图过渡名称都会生成一个 ::view-transition-group() 伪元素,作为子元素, 附加到::view-transition 伪元素上,并包含一个相应的::view-transition-image-pair()。
如果同时存在“旧”和“新”状态, 动态视图过渡样式表中的样式 动画化此伪元素的宽度和 高度, 从旧元素的边框盒大小动画到新元素的 边框盒大小。
同时,元素的变换 从旧元素的屏幕空间变换动画到新元素的屏幕空间变换。
这些样式是动态生成的,因为动画属性的值是在过渡开始时确定的。
3.2.4. 视图过渡图像对隔离:::view-transition-image-pair()伪元素
::view-transition-image-pair() 伪元素 是一个命名视图过渡伪元素, 表示一对相应的“旧/新”视图过渡捕获。 这个伪元素是相应::view-transition-group()伪元素的 子元素, 并包含一个相应的::view-transition-old()伪元素 和/或一个相应的::view-transition-new()伪元素(按此顺序)。
3.2.5. 视图过渡旧状态图像:::view-transition-old()伪元素
::view-transition-old() 伪元素 是一个空的命名视图过渡伪元素, 表示“旧”状态的视觉快照,作为替换元素; 如果没有“旧”状态可表示,则省略。 每个::view-transition-old()伪元素 都是相应::view-transition-image-pair()伪元素的 子元素。
注意:图像的内容和自然尺寸 在捕获图像过程中被捕获, 并在设置过渡伪元素时设置。
注意:在动态视图过渡样式表中添加的额外样式, 用于为这些伪元素添加动画,详细信息在设置过渡伪元素和 更新伪元素样式中描述。
3.2.6. 视图过渡新状态图像:::view-transition-new()伪元素
::view-transition-new() 伪元素 (类似于::view-transition-old()伪元素) 是一个空的命名视图过渡伪元素, 表示“新”状态的视觉快照,作为替换元素; 如果没有“新”状态可表示,则省略。 每个::view-transition-new()伪元素 都是相应::view-transition-image-pair()伪元素的 子元素。
注意:图像的内容和自然尺寸 在捕获图像过程中被捕获, 然后在设置过渡伪元素和 更新伪元素样式中设置并更新。
4. 视图过渡布局
视图过渡伪元素的样式、布局和渲染方式类似于普通元素, 但它们起源于快照包含块, 而不是初始包含块, 并在文档其余部分之上的视图过渡层中绘制。
4.1. 快照包含块
快照包含块(snapshot containing block)是一个覆盖窗口所有可能显示页面内容区域的矩形(因此无论根滚动条或交互控件(interactive widgets)如何,都是一致的)。这通常也意味着它对于文档元素(document element)的旧图像(old image)和新元素(new element)来说是一致的。
对于 iframe,快照包含块对应其初始包含块(initial containing block)。
快照包含了 URL 栏(因为它可能被滚动隐藏),也包含了键盘(因为它会出现和消失)。
顶部和底部栏属于操作系统的一部分,而不是浏览器,所以它们不包含在快照包含块中。
这里包括了滚动条,但不包括 URL 栏,因为网页内容不会出现在那个区域。
快照包含块原点(snapshot containing block origin) 指的是 快照包含块 的左上角。
快照包含块尺寸(snapshot containing block size) 指的是 快照包含块 的宽度和高度,用两个数字的元组(tuple)表示。
快照包含块 被视为 绝对定位包含块(absolute positioning containing block) 和 固定定位包含块(fixed positioning containing block),适用于 ::view-transition 及其后代元素。
4.2. 视图过渡绘制顺序
本规范在CSS2 §E 叠层上下文的详细描述的绘制顺序末尾引入了一个新的叠层,称为 视图过渡层, [CSS2]
::view-transition伪元素生成了一个新的叠层上下文, 称为视图过渡层, 它在文档的所有其他内容(包括在顶层中渲染的任何内容)之后绘制, 在应用于这些内容的所有滤镜和效果之后。 (它不受这些滤镜或效果的影响,除非它们影响 ::view-transition-old()和 ::view-transition-new()伪元素的渲染内容)。
注意:此功能的目的是能够捕获页面内容,包括顶层元素。 为了实现这一点,视图过渡层不能成为捕获的叠层上下文的一部分, 因为这会导致循环依赖。 因此,视图过渡层是所有其他内容的兄弟元素。
当一个 Document
的
激活视图过渡(active view transition) 的
阶段(phase)为
"animating
" 时,
该 Document
中
任何被视图过渡捕获的元素及其
元素内容(element contents)所生成的盒,
除了过渡根伪元素(transition root pseudo-element)的
包含后代(inclusive descendants)外,
都不会被绘制(就如同它们有 visibility: hidden)并且
不响应命中测试(就如同它们有 pointer-events: none)。
注意:参与过渡的元素需要在其 DOM 位置跳过绘制,因为它们的图像会被绘制到相应的 ::view-transition-new() 伪元素中。 同样,命中测试也会被跳过,因为元素的 DOM 位置不再对应其内容实际渲染的位置。 不过,这些元素通过辅助技术或可访问性树的访问方式不会发生变化。
5. 用户代理样式表
全局视图过渡用户代理样式表 是包含以下规则的用户代理来源样式表:
:root{ view-transition-name : root; } :root::view-transition{ position : fixed; inset : 0 ; } :root::view-transition-group ( *) { position : absolute; top : 0 ; left : 0 ; animation-duration : 0.25 s ; animation-fill-mode : both; } :root::view-transition-image-pair ( *) { position : absolute; inset : 0 ; animation-duration : inherit; animation-fill-mode : inherit; animation-delay : inherit; } :root::view-transition-old ( *), :root::view-transition-new ( *) { position : absolute; inset-block-start : 0 ; inline-size : 100 % ; block-size : auto; animation-duration : inherit; animation-fill-mode : inherit; animation-delay : inherit; } /* 默认淡入淡出过渡动画 */ @keyframes -ua-view-transition-fade-out{ to{ opacity : 0 ; } } @keyframes -ua-view-transition-fade-in{ from{ opacity : 0 ; } } /* 当有两个图像时进行混合的关键帧动画 */ @keyframes -ua-mix-blend-mode-plus-lighter{ from{ mix-blend-mode : plus-lighter} to{ mix-blend-mode : plus-lighter} }
解释性摘要
此用户代理样式表执行了以下操作:-
将 ::view-transition 布局为覆盖整个 快照包含块(snapshot containing block),以便每个 :view-transition-group() 子元素可以相对于它进行布局。
-
为 根元素(root element) 设置默认的 视图过渡名称(view transition name),以便能够独立选中它。
-
减少 ::view-transition-image-pair() 伪元素对布局的干扰, 这样开发者在大多数情况下基本可以将 ::view-transition-old() 和 ::view-transition-new() 视为 ::view-transition-group() 的直接子元素。
-
在树中继承动画时序,因此默认情况下,在 ::view-transition-group() 上设置的动画时序会决定所有其后代元素的动画时序。
-
为元素捕获的 ::view-transition-old() 和 ::view-transition-new() 设置样式,使其尺寸和位置尽量与 ::view-transition-group() 保持一致(在不破坏其长宽比的前提下),以便在它们之间进行插值动画。由于这些元素的尺寸依赖于逻辑与物理坐标的映射,动态视图过渡样式表会从 DOM 元素复制相关样式。
-
为每个 ::view-transition-group() 设置默认的四分之一秒淡入淡出动画。
在用户代理来源的 视图过渡期间, 通过动态视图过渡样式表 额外添加样式。
6. API
6.1.
对 Document
的扩展
partial interface Document {ViewTransition startViewTransition (optional UpdateCallback ); };
updateCallback callback =
UpdateCallback Promise <any > ();
-
viewTransition
=document
.startViewTransition
(updateCallback
) -
启动一个新的视图过渡(如果存在,将取消
document
的现有活动视图过渡)。updateCallback
(如果提供的话)会在文档当前状态被捕获后异步调用。 随后,当updateCallback
返回的 Promise 被解决时, 文档的新状态会被捕获,并且过渡(transition)会被发起。请注意,
updateCallback
(如果提供)总是会被调用, 即使过渡无法发生(例如因为存在重复的view-transition-name
值)。 过渡只是对状态变更的增强,因此过渡创建失败绝不会阻止状态的更改。 有关此原则的更多细节,请参见 § 1.4 作为增强的过渡(Transitions as an enhancement)。如果由
updateCallback
返回的Promise被拒绝,则跳过该过渡。
6.1.1.
startViewTransition()
方法步骤
startViewTransition(updateCallback)
的方法步骤如下:
-
令 transition 为 当前对象(this)的 相关 Realm 中新建的
ViewTransition
对象。 -
如果提供了 updateCallback,则将 transition 的 update callback 设为 updateCallback。
-
令 document 为 当前对象(this)的 相关全局对象(relevant global object)的 关联文档(associated document)。
-
如果 document 的 visibility state 为 "
hidden
",则用 "InvalidStateError
"DOMException
跳过 transition,并返回 transition。 -
如果 document 的 激活视图过渡(active view transition) 不为 null,则用 "
AbortError
"DOMException
在 当前对象(this)的 相关 Realm 跳过该视图过渡。注意: 这可能导致两个异步 update callback 并发运行(因此可能无序):一个属于 document 当前的 激活视图过渡,另一个属于本次 transition。按照本特性的设计,假定开发者会用其它机制或框架正确调度这些 DOM 变更。
-
将 document 的 激活视图过渡 设置为 transition。
注意: 视图过渡的流程会在设置视图过渡(setup view transition),通过 执行待处理过渡操作(perform pending transition operations)继续进行。
-
返回 transition。
6.2.
ViewTransition
接口
[Exposed =Window ]interface {
ViewTransition readonly attribute Promise <undefined >;
updateCallbackDone readonly attribute Promise <undefined >;
ready readonly attribute Promise <undefined >;
finished undefined skipTransition (); };
ViewTransition
接口表示并控制一个同文档的视图过渡,即起始文档和结束文档相同,但可能会对文档的 DOM 结构进行更改。
-
viewTransition
.updateCallbackDone
-
一个 Promise,当
updateCallback
返回的 Promise 解决时会被解决,当它被拒绝时则会被拒绝。注意:视图过渡 API 封装了 DOM 更改并创建了视觉过渡。然而,有时你并不关心过渡动画的成功或失败,只想知道 DOM 何时发生变化。
updateCallbackDone
适用于这种情况。) -
viewTransition
.ready
-
一个 Promise,一旦创建了过渡的伪元素,并且动画即将开始时会被解决。
如果无法开始过渡,则会被拒绝。这可能是由于配置错误,例如重复的 'view-transition-name',或者
updateCallbackDone
返回了一个被拒绝的 Promise。ready
解决的时刻是使用 Web Animation API 来为视图过渡伪元素添加动画的理想时机。 -
viewTransition
.finished
-
一个 Promise,一旦结束状态完全可见并且可供用户交互时就会被解决。
它只有在
updateCallback
返回了一个被拒绝的 Promise 时才会被拒绝,因为这表明未能创建结束状态。否则,如果过渡未能开始,或被跳过(通过
skipTransition()
),结束状态仍然会达到,因此finished
会被解决。 -
viewTransition
.skipTransition
() -
立即完成过渡,或者阻止其开始。
这永远不会阻止
updateCallback
的调用,因为 DOM 更改独立于过渡。有关此原则的更多详细信息,请参见§ 1.4 作为增强的过渡。如果
finished
尚未解决,它将与updateCallbackDone
一起解决或被拒绝。
一个 ViewTransition
拥有以下内容:
- 命名元素(named elements)
-
一个映射(map),其键为视图过渡名称(view transition name),值为被捕获的元素(captured elements)。初始时为一个新的映射(map)。
注:由于该属性与ViewTransition
相关联,当调用 清除视图过渡(Clear view transition) 时会被清理。 - 阶段(phase)
-
以下有序阶段之一,初始为 "
pending-capture
":-
"
pending-capture
"。 -
"
update-callback-called
"。 -
"
animating
"。 -
"
done
"。
注意:对大多数开发者来说,使用该 API 时无需关心各个阶段,因为它们会自动推进。但了解每个阶段发生的步骤(如快照何时捕获、伪元素 DOM 何时创建等)很重要。下文对各个阶段的描述力求精确,旨在为实现者提供明确的规范实现步骤。
-
- 更新回调(update callback)
-
一个
UpdateCallback
或 null,初始为 null。 - ready promise
-
一个
Promise
。初始为 新建的 Promise,位于 当前对象的 相关 Realm 中。 - update callback done promise
-
一个
Promise
。初始为 新建的 Promise,位于 当前对象的 相关 Realm 中。注意:ready promise 和 update callback done promise 会被立即创建,因此如果 Promise 被拒绝(rejection),会产生
unhandledrejection
,除非被 处理,即使未访问updateCallbackDone
等 getter。 - finished promise
-
一个
Promise
。初始为 新建的 Promise,位于 当前对象的 相关 Realm,标记为已处理。注意:此 Promise 被标记为已处理,以避免重复的
unhandledrejection
,因为该 Promise 只会随着 update callback done promise 一起被拒绝。 - 过渡根伪元素(transition root pseudo-element)
-
一个 ::view-transition。初始为新的 ::view-transition。
- 初始快照包含块尺寸(initial snapshot containing block size)
-
一个包含两个数字(宽度和高度)的元组(tuple),或 null。初始为 null。
finished
的 getter 步骤为返回 当前对象的 finished
promise。
ready
的 getter 步骤为返回 当前对象的 ready promise。
updateCallbackDone
的 getter 步骤为返回 当前对象的 update callback done promise。
6.2.1.
skipTransition()
方法步骤
方法步骤(method steps)如下,适用于 skipTransition()
:
-
如果当前对象(this)的阶段(phase)不是 "
done
",则用 "AbortError
"DOMException
,为当前对象跳过视图过渡(skip the view transition)。
7. 算法
7.1. 数据结构
7.1.1.
对 Document
的扩展
Document
还具有以下内容:
- 激活视图过渡(active view transition)
-
一个
ViewTransition
或 null。初始为 null。 - 视图过渡的渲染抑制(rendering suppression for view transitions)
-
一个布尔值。初始为 false。
当
Document
的 视图过渡的渲染抑制 为 true 时, 所有指针命中测试都必须只针对其 文档元素(document element), 忽略其它所有元素。注意:这不会影响已被捕获(captured)的指针。
- 动态视图过渡样式表(dynamic view transition style sheet)
-
一个样式表(style sheet)。初始为用户代理源(user-agent origin)中新建的样式表,排序在全局视图过渡用户代理样式表之后。
注意:该样式表用于保存与过渡相关的动态样式。
- 显示视图过渡树(show view transition tree)
-
一个布尔值。初始为 false。
当其值为 true 时,当前对象的 激活视图过渡的 过渡根伪元素(transition root pseudo-element) 会作为 当前对象的 文档元素的子元素渲染,其 文档元素 是其 原始元素(originating element)。
注意:过渡根伪元素在文档元素中的位置无关紧要,因为该伪元素的包含块(containing block)是快照包含块(snapshot containing block)。
7.1.2. 元素的扩展
元素具有一个 在视图过渡中捕获 的布尔值,初始值为 false。
注意:此规范使用 CSS 对 元素 的定义,其中包括 伪元素。
7.1.3. 捕获元素
捕获元素是一个具有以下内容的 结构体:
- 旧图像(old image)
-
一个 2D 位图或 null。初始为 null。
-
旧宽度(old width)
- 旧高度(old height)
-
一个
unrestricted double
,初始为 0。 - 旧变换(old transform)
-
一个 <transform-function>,初始为恒等变换函数(identity transform function)。
- 旧 writing-mode
-
null 或 writing-mode,初始为 null。
- 旧 direction
-
null 或 direction,初始为 null。
- 旧 text-orientation
-
null 或 text-orientation,初始为 null。
- 旧 mix-blend-mode
-
null 或 mix-blend-mode,初始为 null。
- 旧 backdrop-filter
-
null 或 backdrop-filter,初始为 null。
- 旧 color-scheme
-
null 或 color-scheme,初始为 null。
- 新元素(new element)
-
一个元素(element)或 null。初始为 null。
此外,捕获元素 具有以下 样式定义:
- 组关键帧
-
一个
CSSKeyframesRule
或 null。初始值为 null。 - 组动画名称规则
-
一个
CSSStyleRule
或 null。初始值为 null。 - 组样式规则
-
一个
CSSStyleRule
或 null。初始值为 null。 - 图像对隔离规则
-
一个
CSSStyleRule
或 null。初始值为 null。 - 图像动画名称规则
-
一个
CSSStyleRule
或 null。初始值为 null。
注意:这些用于从 文档 的 动态视图过渡样式表 中更新并稍后移除样式。
7.2. 执行待定的过渡操作
要执行待处理过渡操作(perform pending transition
operations),给定一个 Document
document,执行以下步骤:
-
如果 document 的 激活视图过渡(active view transition) 不为 null,则:
-
如果 document 的 激活视图过渡的 阶段(phase)为 "
pending-capture
",则为 document 的 激活视图过渡 设置视图过渡(setup view transition)。 -
否则,如果 document 的 激活视图过渡的 阶段(phase)为 "
animating
",则为 document 的 激活视图过渡 处理过渡帧(handle transition frame)。
-
7.3. 设置视图过渡
ViewTransition
transition,
执行以下步骤:
注意: 该算法捕获文档的当前状态,
调用过渡的 UpdateCallback
,
然后捕获文档的新状态。
-
令 document 为 transition 的 相关全局对象(relevant global object)的 关联文档(associated document)。
-
为 transition 捕获旧状态(Capture the old state)。
如果返回失败,则用 "
InvalidStateError
"DOMException
在 transition 的 相关 Realm 跳过视图过渡(skip the view transition),然后返回。 -
将 document 的 视图过渡的渲染抑制(rendering suppression for view transitions) 设为 true。
-
在 DOM 操作任务源(DOM manipulation task source)上, 针对 transition 的 相关全局对象, 排队一个全局任务(Queue a global task),以执行以下步骤:
注意: 此处排队任务是因为在捕获图像时纹理读取可能是异步的,尽管 HTML 规范中的渲染步骤表现为同步。
ViewTransition
transition,
执行以下步骤:
-
如果 transition 的 阶段(phase)为 "
done
",则返回。注意: 如果 transition 在此之前被跳过,就会发生这种情况。
-
将 视图过渡的渲染抑制(rendering suppression for view transitions) 设为 false。
-
如果 transition 的 初始快照包含块尺寸(initial snapshot containing block size) 不等于 快照包含块尺寸(snapshot containing block size),则为 transition 跳过视图过渡,并返回。
-
为 transition 捕获新状态(Capture the new state)。
如果返回失败,则用 "
InvalidStateError
"DOMException
在 transition 的 相关 Realm 跳过视图过渡,然后返回。 -
解决(Resolve) transition 的 update callback done promise,值为 undefined。
-
对于每个 capturedElement 属于 transition 的 命名元素(named elements)的值:
-
如果 capturedElement 的 新元素(new element) 不为 null,则将 capturedElement 的 新元素的 视图过渡捕获状态(captured in a view transition) 设为 true。
-
-
为 transition 设置过渡伪元素(Setup transition pseudo-elements)。
-
为 transition 更新伪元素样式(Update pseudo-element styles)。
如果返回失败,则用 "
InvalidStateError
"DOMException
在 transition 的 相关 Realm 跳过视图过渡,然后返回。注意: 上述步骤需要运行文档生命周期阶段,以计算样式/布局过程中产生的信息。
-
将 transition 的 阶段(phase)设为 "
animating
"。 -
解决(Resolve) transition 的 ready promise。
7.3.1. 捕获旧状态
ViewTransition
transition:
-
令 document 为 transition 的 相关全局对象(relevant global object)的 关联文档(associated document)。
-
令 namedElements 为 transition 的 命名元素(named elements)。
-
令 usedTransitionNames 为新的字符串集合(set)。
-
令 captureElements 为新的元素列表(list)。
-
如果快照包含块尺寸(snapshot containing block size)超过实现自定义(implementation-defined)的最大值,则返回失败。
-
将 transition 的 初始快照包含块尺寸(initial snapshot containing block size) 设为快照包含块尺寸。
-
对于每个 element,属于所有已连接的元素(connected element)并且其节点文档等于 document,按绘制顺序(paint order)遍历:
以绘制顺序遍历,确保该顺序被缓存于 namedElements。这定义了 ::view-transition-group 伪元素的 DOM 顺序,使得在绘制栈底部的元素会生成 ::view-transition 的第一个伪子元素。-
如果该 element 的任何平坦树(flat tree)祖先跳过其内容(skips its contents),则继续(continue)。
-
如果 element 有多个盒片段(box fragment),则继续。
注意:未来版本可能会支持对分片元素的过渡。参见 #8900。
-
令 transitionName 为 element 的 view-transition-name 的计算值(computed value)。
-
如果 transitionName 为 none,或 element 未被渲染(not rendered),则继续。
-
如果 usedTransitionNames 包含 transitionName,则返回失败。
-
添加 transitionName 到 usedTransitionNames。
-
将 element 的 视图过渡捕获状态(captured in a view transition) 设为 true。
-
添加 element 到 captureElements。
算法将继续执行一个独立循环,以确保所有参与捕获的元素的 视图过渡捕获状态 都被设为 true,然后再被后续步骤读取。 -
-
对于每个 element 属于 captureElements:
-
令 capture 为新的捕获元素结构体(captured element struct)。
-
将 capture 的 旧图像(old image) 设为 捕获 element 图像 的结果。
-
令 originalRect 为,如果 element 是 文档元素(document element),则为快照包含块(snapshot containing block),否则为该元素的边框盒(border box)。
-
将 capture 的 旧宽度(old width) 设为 originalRect 的
width
。 -
将 capture 的 旧高度(old height) 设为 originalRect 的
height
。 -
将 capture 的 旧变换(old transform) 设为一个 <transform-function>,该函数会将 element 的边框盒(border box)从快照包含块原点(snapshot containing block origin)映射到其当前视觉位置。
-
将 capture 的 旧 writing-mode 设为 element 上 writing-mode 的计算值。
-
将 capture 的 旧 direction 设为 element 上 direction 的计算值。
-
将 capture 的 旧 text-orientation 设为 element 上 text-orientation 的计算值。
-
将 capture 的 旧 mix-blend-mode 设为 element 上 mix-blend-mode 的计算值。
-
将 capture 的 旧 backdrop-filter 设为 element 上 backdrop-filter 的计算值。
-
将 capture 的 旧 color-scheme 设为 element 上 color-scheme 的计算值。
-
令 transitionName 为 element 的 view-transition-name 的计算值。
-
将 namedElements[transitionName] 设为 capture。
-
-
对于每个 element 属于 captureElements:
-
将 element 的 视图过渡捕获状态(captured in a view transition) 设为 false。
-
7.3.2. 捕获新状态
ViewTransition
transition:
-
令 document 为 transition 的 相关全局对象(relevant global object)的 关联文档(associated document)。
-
令 namedElements 为 transition 的 命名元素(named elements)。
-
令 usedTransitionNames 为新的字符串集合(set)。
-
对于每个 element,属于所有已连接的元素(connected element),且其节点文档等于 document,按绘制顺序(paint order)遍历:
-
如果该 element 的任何平坦树(flat tree)祖先跳过其内容(skips its contents),则继续(continue)。
-
令 transitionName 为 element 的 view-transition-name 的计算值(computed value)。
-
如果 transitionName 为 none,或 element 未被渲染(not rendered),则继续。
-
如果 usedTransitionNames 包含 transitionName,则返回失败。
-
添加 transitionName 到 usedTransitionNames。
-
如果 namedElements[transitionName] 不存在,则将 namedElements[transitionName] 设为新的捕获元素结构体(captured element struct)。
注意:我们特意将该结构体加入有序映射的末尾。这意味着仅存在于新 DOM 的名称(入场动画)会绘制在仅存在于旧 DOM 的名称(离场动画)和同时存在于新旧 DOM 的名称(配对动画)之上。这未必适用于所有分层情况,参见issue 8941。
-
将 namedElements[transitionName] 的 新元素(new element) 设为 element。
-
7.3.3. 设置过渡伪元素
ViewTransition
transition:
注意:该算法构建了用于过渡的伪元素树,并生成了初始样式。 伪树的结构在更高级别的 § 3.2 视图过渡伪元素 中介绍。
-
令 document 为 当前对象(this)的 相关全局对象的 关联文档(associated document)。
-
将 document 的 显示视图过渡树(show view transition tree)设为 true。
-
对于每对 transitionName → capturedElement 属于 transition 的 命名元素(named elements):
-
令 group 为新的 ::view-transition-group(),其 视图过渡名称(view transition name) 设为 transitionName。
-
将 group 添加到 transition 的 过渡根伪元素(transition root pseudo-element)。
-
令 imagePair 为新的 ::view-transition-image-pair(),其 视图过渡名称 设为 transitionName。
-
将 imagePair 添加到 group。
-
如果 capturedElement 的 旧图像(old image) 不为 null,则:
-
令 old 为新的 ::view-transition-old(),其 视图过渡名称 设为 transitionName,并以 capturedElement 的 旧图像 作为其 替换内容(replaced content)显示。
-
将 old 添加到 imagePair。
-
-
如果 capturedElement 的 新元素(new element) 不为 null,则:
-
令 new 为新的 ::view-transition-new(),其 视图过渡名称 设为 transitionName。
注意:该伪元素的样式由 更新伪元素样式(update pseudo-element styles)处理。
-
将 new 添加到 imagePair。
-
-
如果 capturedElement 的 旧图像为 null,则:
-
断言(Assert):capturedElement 的 新元素 不为 null。
-
将 capturedElement 的 图像动画名称规则(image animation name rule) 设为新的
CSSStyleRule
,表示如下 CSS,并添加到 document 的 动态视图过渡样式表(dynamic view transition style sheet)::root:
:view-transition-new ( transitionName) { animation-name : -ua-view-transition-fade-in; } 注意:上述代码示例包含待替换的变量。
-
-
如果 capturedElement 的 新元素为 null,则:
-
将 capturedElement 的 图像动画名称规则 设为新的
CSSStyleRule
,表示如下 CSS,并添加到 document 的 动态视图过渡样式表::root:
:view-transition-old ( transitionName) { animation-name : -ua-view-transition-fade-out; } 注意:上述代码示例包含待替换的变量。
-
如果 capturedElement 的 旧图像和 新元素均不为 null,则:
-
令 transform 为 capturedElement 的 旧变换(old transform)。
-
令 width 为 capturedElement 的 旧宽度(old width)。
-
令 height 为 capturedElement 的 旧高度(old height)。
-
令 backdropFilter 为 capturedElement 的 旧 backdrop-filter。
-
将 capturedElement 的 组关键帧规则(group keyframes) 设为新的
CSSKeyframesRule
,表示如下 CSS,并添加到 document 的 动态视图过渡样式表:@keyframes -ua-view-transition-group-anim-transitionName{ from{ transform : transform; width : width; height : height; backdrop-filter : backdropFilter; } } 注意:上述代码示例包含待替换的变量。
-
将 capturedElement 的 组动画名称规则(group animation name rule) 设为新的
CSSStyleRule
,表示如下 CSS,并添加到 document 的 动态视图过渡样式表::root:
:view-transition-group ( transitionName) { animation-name : -ua-view-transition-group-anim-transitionName; } 注意:上述代码示例包含待替换的变量。
-
将 capturedElement 的 图像对隔离规则(image pair isolation rule) 设为新的
CSSStyleRule
,表示如下 CSS,并添加到 document 的 动态视图过渡样式表::root:
:view-transition-image-pair ( transitionName) { isolation : isolate; } 注意:上述代码示例包含待替换的变量。
-
将 capturedElement 的 图像动画名称规则 设为新的
CSSStyleRule
,表示如下 CSS,并添加到 document 的 动态视图过渡样式表::root:
:view-transition-old ( transitionName) { animation-name : -ua-view-transition-fade-out, -ua-mix-blend-mode-plus-lighter; } :root::view-transition-new ( transitionName) { animation-name : -ua-view-transition-fade-in, -ua-mix-blend-mode-plus-lighter; } 注意:上述代码示例包含待替换的变量。
注意:mix-blend-mode: plus-lighter 可确保旧图像和新图像相同像素的混合结果为相同色值,实现“正确”的交叉淡入淡出。
-
-
7.4. 调用更新回调
ViewTransition
transition,执行如下步骤:
注意: 该步骤对每一个 ViewTransition
都保证会被调用,即使该过渡已被跳过。原因详见 § 1.4
作为增强的过渡。
-
断言:transition 的 阶段(phase)为 "
done
",或在 "update-callback-called
" 之前。 -
令 callbackPromise 为 null。
-
如果 transition 的 更新回调(update callback)为 null,则将 callbackPromise 设为 解析为 undefined 的 promise,位于 transition 的 相关 Realm。
-
如果 transition 的 阶段不是 "
done
",则将其 阶段设为 "update-callback-called
"。 -
令 fulfillSteps 为以下步骤:
-
激活视图过渡(Activate view transition) transition。
-
解决(Resolve) transition 的 update callback done promise,值为 undefined。
注意:若上一步已解决该 promise,则本步无影响。
-
-
令 rejectSteps 为下列步骤,参数为 reason:
-
拒绝(Reject) transition 的 update callback done promise,原因为 reason。
-
如果 transition 的 阶段为 "
done
",则返回。注意:如果 transition 在此之前被跳过,就会发生这种情况。
-
标记为已处理(Mark as handled) transition 的 ready promise。
注意:transition 的 update callback done promise 会提供
unhandledrejection
。本步避免重复。 -
跳过视图过渡(Skip the view transition) transition,并传入 reason。
-
-
监听 callbackPromise,当其解决时执行 fulfillSteps,拒绝时执行 rejectSteps。
-
如需在超时后跳过过渡,用户代理可并行执行以下步骤:
-
等待一个实现自定义的时长(duration)。
-
在 DOM 操作任务源(DOM manipulation task source)上, 针对 transition 的 相关全局对象, 排队一个全局任务(Queue a global task),以执行以下步骤:
-
如果 transition 的 阶段为 "
done
",则返回。注意:如果 transition 在此之前被跳过,就会发生这种情况。
-
跳过 transition,并抛出 "
TimeoutError
"DOMException
。
-
-
7.5. 跳过视图过渡
ViewTransition
transition 使用原因 reason 跳过视图过渡:
-
如果 transition 的 阶段处于 "
调用更新回调之前
",则在 transition 的 相关全局对象的基础上,队列一个全局任务到 DOM 操作任务来源,以调用更新回调。 -
将 视图过渡的渲染抑制设置为 false。
-
将 transition 的 阶段设置为 "
完成
"。 -
拒绝 transition 的 准备 promise,原因是 reason。
注意: 此 准备 promise可能已经在此时被解析, 如果在开始动画后调用
skipTransition()
, 则此步骤将无效。 -
解析 transition 的 完成 promise,以 响应 transition 的 更新回调完成的 promise的结果:
-
如果 promise 被满足,则返回 undefined。
注意: 由于 transition 的 更新回调完成 promise 的拒绝未被显式处理, 如果 transition 的 更新回调完成 promise被拒绝, 则 transition 的 完成 promise将以相同原因被拒绝。
-
7.6. 视图过渡页面可见性变化步骤
Document
document 为:
-
如果 document 的 可见状态是 "
隐藏
",则:-
如果 document 的 活动视图过渡不是 null,则使用 "
InvalidStateError
"DOMException
跳过 document 的 活动视图过渡。
-
注意: 此步骤由 HTML 规范调用。
7.7. 捕获图像
-
如果 element 是 文档元素,那么:
-
渲染文档的区域(包括其 画布背景和任何顶层内容), 该区域与 快照包含块相交, 在一个与 快照包含块大小相同的透明画布上, 按照捕获渲染特性及以下附加特性进行渲染:
-
应将 element 的 滚动框外部区域渲染为已滚动到的状态,而不移动或调整 布局视口的大小。 此操作不得触发与滚动或调整大小相关的事件,例如
IntersectionObserver
。用户看到的内容与捕获的快照的示例。 此示例假设根元素是唯一具有过渡名称的元素。 -
不能滚动到的区域(即超出滚动边界的区域), 应渲染为画布背景。
用户看到的内容与捕获的快照的示例。 此示例假设根元素是唯一具有过渡名称的元素。
-
-
将此画布作为图像返回。 图像的自然大小等于 快照包含块。
-
-
否则:
7.7.1. 捕获渲染特性
-
如果引用的元素或其祖先应用了变换(transform),则忽略该变换。
注意: 此变换通过相关的 ::view-transition-group 伪元素的
transform
属性应用于快照。 -
应用于元素及其后代的效果,例如 不透明度(opacity) 和 滤镜(filter),会应用到捕获中。 从其祖先应用于元素的效果将被忽略。
-
如果墨水溢出矩形超出某些实现定义的最大值,可能会被裁剪。 然而,捕获的图像至少应该包含与 快照包含块相交的 element 的内容。 实现可能会调整光栅化质量,以适应通过变换进入视图的大墨水溢出区域的元素。
-
对于每个 descendant 的 包括阴影的后代
元素(Element)
和 伪元素的 element, 如果 descendant 被捕获在视图过渡中, 则跳过绘制 descendant。注意: 这是必要的,因为后代会生成自己的快照,并独立显示和动画。
7.8. 处理过渡帧
ViewTransition
transition:
-
设定 hasActiveAnimations 为布尔值,初始值为 false。
-
如果 hasActiveAnimations 为 false:
-
将 transition 的 阶段 设置为 "
完成
"。 -
清除视图过渡 transition。
-
解析 transition 的 完成的 promise。
-
返回。
-
-
如果 transition 的 初始快照包含块大小 不等于 快照包含块大小, 则跳过视图过渡 transition,并返回。
-
更新伪元素样式 transition。
如果返回失败,则跳过视图过渡 transition,并在 transition 的 相关领域中返回 "
InvalidStateError
"DOMException
。注意: 上述内容表明,传入元素的大小或位置的变化将导致生成新的关键帧。 这可能导致视觉跳跃。 我们可以平滑地重新定位,但没有用例来证明其复杂性的合理性。 有关详细信息,请参阅 第7813号问题。
7.9. 更新伪元素样式
ViewTransition
transition:
-
对于每个 transitionName → capturedElement 的 transition 的 命名元素:
-
将 width, height, transform, writingMode, direction, textOrientation, mixBlendMode, backdropFilter 和 colorScheme 设置为 null。
-
如果 capturedElement 的 新元素 为 null,那么:
-
将 width 设置为 capturedElement 的 旧宽度。
-
将 height 设置为 capturedElement 的 旧高度。
-
将 transform 设置为 capturedElement 的 旧变换。
-
将 writingMode 设置为 capturedElement 的 旧写入模式。
-
将 direction 设置为 capturedElement 的 旧方向。
-
将 textOrientation 设置为 capturedElement 的 旧文本方向。
-
将 mixBlendMode 设置为 capturedElement 的 旧混合模式。
-
将 backdropFilter 设置为 capturedElement 的 旧背景滤镜。
-
将 colorScheme 设置为 capturedElement 的 旧配色方案。
-
-
否则:
-
如果 capturedElement 的 组样式规则 为 null, 则将 capturedElement 的 组样式规则 设置为一个新的
CSSStyleRule
表示以下 CSS, 并将其附加到 transition 的 相关全局对象 的 关联文档 的 动态视图过渡样式表。否则,更新 capturedElement 的 组样式规则 以匹配以下 CSS:
:root:
:view-transition-group ( transitionName) { width : width; height : height; transform : transform; writing-mode : writingMode; direction : direction; text-orientation : textOrientation; mix-blend-mode : mixBlendMode; backdrop-filter : backdropFilter; color-scheme : colorScheme; } 注意: 上述代码示例包含需要替换的变量。
-
如果 capturedElement 的 新元素 不为 null,那么:
-
设定 new 为 ::view-transition-new() ,使用视图过渡名称 transitionName。
-
-
如果其效果可以被 Web API 观察到,则必须执行此算法以更新用户代理源中的样式。
注意:此类 Web API 的一个示例是
window.getComputedStyle(document.documentElement, "::view-transition")
。
7.10. 清除视图过渡
ViewTransition
transition:
隐私考虑
本规范未引入新的隐私考虑。
安全考虑
使用捕获图像算法生成的图像可能包含跨域数据(如果文档嵌入了跨域资源)或敏感信息,如访问过的链接。实现必须确保这些数据无法被文档访问。这应该是可行的,因为在文档的默认渲染中,访问这些数据已经被阻止。
附录 A. 变更
本附录是信息性的。
自2022-05-30 工作草案的变更
-
使用关键帧在交叉渐变期间添加 Plus-Lighter 混合。参见 问题 8924。
-
将 mix-blend-mode 添加到复制到 ::view-transition-group 的属性列表。参见 问题 8962。
-
将 text-orientation 添加到复制到 ::view-transition-group 的属性列表。参见 问题 8230。
-
重构旧捕获算法以在读取值之前正确设置 捕获在视图过渡中。
-
使
startViewTransition()
参数变为不可为空。参见 问题 9460。 -
类似于变换/大小动画背景滤镜。参见 问题 9358。
-
从 DOM 元素复制
color-scheme
到 ::view-transition-group()。参见 问题 9276。 -
添加关于为什么 view-transition-name 应该是可动画的注释。
-
view-transition-name: auto
应为一个无效值。参见 问题 9639。 -
添加注释以解释入口动画的绘制顺序。参见 问题 9672。
-
添加注释以解释命名元素如何清理。参见 问题 9669。
-
重构算法以明确时间,特别是 `updateCallbackDone` 的时间。参见 问题 9762。
-
为 UA 样式表规则添加动画延迟继承(::view-transition)-image-pair,-old 和 -new。参见 问题 9817。
-
当文档隐藏时自动跳过动画。参见 问题 9543。
-
删除与跨文档视图过渡的引用,以保持 L1 规范的简洁。参见 问题 9886。
-
导出一个算法以在页面隐藏时跳过活动过渡。参见 问题 9543。
自2022-05-25 工作草案的变更
-
修复 ::view-transition-new 用户代理样式表中的拼写错误。参见拉取请求。
自2022-11-24 工作草案的变更
-
当渲染被抑制时,指针事件会解析到 documentElement。参见 问题 7797。
-
从 UA 样式表中移除 HTML 特定内容,以支持 SVG 文档上的视图过渡。
-
将 updateDOMCallback 重命名为
UpdateCallback
。 参见 问题 8144。 -
将快照视口重命名为 快照包含块。
-
如果视口大小发生变化则跳过过渡。参见 问题 8045。
-
添加对 :only-child 的支持。参见 问题 8057。
-
当跳过过渡时,
UpdateCallback
在自己的任务中调用,而不是同步调用。参见 问题 7904 -
捕获图像时,至少应该捕获图像的视口内部分,如果需要可以缩小。参见 问题 8561。
-
片段化的元素不参与视图过渡。参见 问题 8339。
-
将 “快照根” 重命名为 “快照包含块”,并使其成为后代的 绝对定位包含块 和 固定定位包含块 。参见 问题 8505。
自2022-10-25 工作草案 (FPWD)的变更
-
添加动态视图过渡样式表的概念,用于为当前文档动态生成 UA 样式。
-
添加快照视口概念。参见问题 7859。
-
澄清在跳过过渡时解决/拒绝 promise 的时间。参见问题 7956。
-
在跳过其内容的 content-visibility:auto 元素下的元素将被忽略。参见问题 7874。
-
伪 DOM 上的 UA 样式与作者 DOM 同步,以便任何开发人员可观察到的 API。参见问题 7812。
-
在 updateCallback 期间抑制渲染。参见问题 7784。
-
新文档中元素的大小/位置变化会生成新的 UA 动画关键帧。参见问题 7813。
-
使用 -ua- 前缀将关键帧限定到用户代理样式表中。参见问题 7560。
-
更新伪元素名称为 view-transition*。参见问题 7960。
-
更新伪元素的选择器语法。参见问题 7788。
-
添加安全/隐私考虑部分。