likes
comments
collection
share

[译]查看 Angular 对 View Transitions API 的支持

作者站长头像
站长
· 阅读数 17

[译]查看 Angular 对 View Transitions API 的支持

当用户从一个路由导航到另一个路由时,Angular Router 会将 URL 路径映射到相关组件并显示其视图。将路线转换动画化可以极大地增强用户体验。在版本 17 中,当在 Chrome/Chromium 浏览器中的路由之间导航时,路由器现在支持 View Transitions API

视图转换如何工作

用于视图转换的原生浏览器方法是 document.startViewTransition。当调用 startViewTransition() 时,浏览器会捕获页面的当前状态,其中包括截图。

该方法采用更新 DOM 的回调,并且该函数可以是异步的。当回调返回的 Promise 解析时,将捕获新状态并在下一个动画帧中开始转换。

以下是 startViewTransition API 的示例:

document.startViewTransition(async () => {
  await updateTheDOMSomehow();
});

如果您想了解更多有关浏览器 API 的详细信息,Chrome Explainer 是非常宝贵的资源。

Router 如何使用视图转换

在路由器中启动导航后会发生几件事:路由匹配、加载惰性路由和组件、执行防护和解析器等等。一旦这些成功完成,新路线就可以激活了。

此路由激活是我们想要作为视图转换的一部分执行的 DOM 更新。

启用视图转换功能后,导航将“暂停”并调用浏览器的 startViewTransition 方法。一旦 startViewTransition 回调执行(这是异步发生的,如此处规范中所述),导航将“恢复”。路由器导航的其余步骤包括更新浏览器 URL 以及激活或停用匹配的路由(DOM 更新)。

最后,传递给 startViewTransition 的回调返回一个 Promise,一旦 Angular 完成渲染,该 Promise 就会解析。如上所述,这向浏览器指示应捕获新的 DOM 状态并且应开始转换。

视图转换是一种渐进式增强。如果浏览器不支持该 API,则 Router 将执行 DOM 更新而不调用 startViewTransition,并且导航不会有动画效果。

在路由器中启用视图转换

要启用此功能,请将 withViewTransitions 添加到 ProvideRouter 函数中:

bootstrapApplication(MyApp, { providers: [
  provideRouter(routes, withViewTransitions()),
]});

尝试 StackBlitz 上的“计数”示例

使用 CSS 自定义过渡

可以使用 CSS 自定义视图转换。我们还可以通过设置视图转换名称来指示浏览器为转换创建单独的元素。我们可以通过将 view-transition-name: count 添加到 Counter 组件中的 .count 样式来扩展第一个示例。

然后,在全局样式中,我们可以为此视图转换定义自定义动画:

/* Custom transition */
@keyframes rotate-out {
 to {
   transform: rotate(90deg);
 }
}
@keyframes rotate-in {
 from {
   transform: rotate(-90deg);
 }
}
::view-transition-old(count),
::view-transition-new(count) {
 animation-duration: 200ms;
 animation-name: -ua-view-transition-fade-in, rotate-in;
}
::view-transition-old(count) {
 animation-name: -ua-view-transition-fade-out, rotate-out;
}

在全局样式文件中定义视图过渡动画非常重要。它们不能在组件样式中定义,因为默认视图封装会将样式范围限定到组件。

尝试 StackBlitz 上更新的“count”示例

使用 onViewTransitionCreated 控制转换

还可以使用包含 onViewTransitionCreated 回调的选项对象来调用 withViewTransitions 路由器功能。此回调在注入上下文中运行,并接收一个 ViewTransitionInfo 对象,该对象包括从 startViewTransition 返回的 ViewTransition,以及导航从中转换的 ActivatedRouteSnapshot 和要转换到的新导航。

此回调可用于任意数量的自定义。例如,您可能希望在某些条件下跳过转换。我们在新的 angular.dev 文档网站上使用它:

withViewTransitions({
 onViewTransitionCreated: ({ transition }) => {
   const router = inject(Router);
   const targetUrl = router.getCurrentNavigation()!.finalUrl!;
   // Skip the transition if the only thing 
   // changing is the fragment and queryParams
   const config = { 
     paths: 'exact', 
     matrixParams: 'exact',
     fragment: 'ignored',
     queryParams: 'ignored',
   };

   if (router.isActive(targetUrl, config)) {
     transition.skipTransition();
   }
 },
}),

在此代码片段中,我们从导航将要到达的 ActivatedRouteSnapshot 创建一个 UrlTree。然后,我们检查 Router 以查看此 UrlTree 是否已处于活动状态,忽略片段或查询参数中的任何差异。

如果它已经处于活动状态,我们调用skipTransition,它将跳过视图转换的动画部分。单击锚链接时就会出现这种情况,该链接只会滚动到同一文档中的另一个位置。

Chrome explainer 中适用于 Angular 的示例

我们在 Angular 中重新创建了 Chrome 团队的一些精彩示例,供您探索。

过渡元素不需要是相同的 DOM 元素

自定义进入和退出动画

异步 DOM 更新并等待内容

在此期间,页面被冻结,因此应将此处的延迟保持在最低限度……在某些情况下,最好完全避免延迟,并使用已有的内容。

Angular 路由器中的视图转换功能不提供延迟动画的方法。目前,我们的立场是,使用现有的内容总是比让页面在额外的时间内处于非交互状态更好。

根据导航类型更改转换

过渡时不冻结其他动画

使用 JavaScript 制作动画

今天就试试这个实验性功能吧!

虽然 Angular 对视图转换 API 的支持仍处于实验阶段,但我们对它为用户构建下一代 Web 体验所创造的可能性感到兴奋。该团队将继续努力稳定支持,您可以提供帮助。

尝试此功能并在 GitHub 上留下反馈。我们提供了多个示例供您尝试并享受乐趣。如果您实现了一些很酷的东西,请在 X 上标记我们并向我们展示您创建的很酷的东西。

感谢您成为 Angular 社区的一员并继续构建,直到下一次。

原文:blog.angular.io/check-out-a…