还记得在 2023 年的时候,偶然在 antfu 大佬的一次直播里听闻了 View Transitions API 这个新鲜名词。
当时只是在脑海中浅浅留下了个印象,并未深入探究。然而时光流转,直到最近,由于项目中的特定需求,我才真正静下心来,对 view-transitions-api 进行了全面的了解,并将其应用到实际开发当中。
什么是 View Transitions API
View Transitions API 是一种用于创建动画的浏览器 API,常用于 SPA(单页面应用)中的过渡切换动画。 使用 View Transitions API 可以轻松创建不同 DOM 状态之间的转换动画,避免了编写大量的 CSS 和 JavaScript 来处理新旧内容的共存逻辑。
View Transitions API 目前仍然是一个实验性功能,仅在 Chrome 和 Edge 的 111 及以上版本、Opera 的 75 及以上版本可用,Firefox 和 Safari 暂时不可用。
工作原理
View Transitions API 的工作原理主要基于浏览器对页面视图变化的智能管理和动画处理。
当页面内容需要更新时,开发者通过调用特定的方法,如 document.startViewTransition(callback) 来启动视图过渡。浏览器会在后台自动创建两个页面的快照,一个是更新前的页面,另一个是更新后的页面。
- ::view-transition 是视图过渡叠加层的根元素,它包含所有视图过渡且位于所有其他页面内容的顶部。
- ::view-transition-old 是旧页面视图的屏幕截图,且 ::view-transition-new 是新页面视图的实时展示。
然后,浏览器会分析这两个页面的差异,确定哪些元素需要进行过渡动画。它会根据开发者设置的过渡属性,如持续时间、缓动效果等,来计算每个元素的动画路径和变化过程。
在过渡过程中,浏览器会同时显示旧页面和新页面的元素,并根据计算好的动画路径对元素进行平滑的变换。例如,如果一个元素的位置、大小或颜色发生了变化,浏览器会以流畅的动画方式来展示这种变化,而不是突然的切换。
整个过程中,浏览器会智能地处理元素的层级关系和布局,确保过渡效果自然且符合预期。同时,它还会优化性能,避免不必要的重绘和回流,以提供高效的用户体验。
比如说,当您更新一个列表中的某一项时,浏览器会识别出该项的变化,并将其从旧状态逐渐过渡到新状态,而不是生硬地直接显示新的内容。
通过修改伪元素树实现自定义动画效果
在动画开始执行之前,会实现 Promise ViewTransition.ready
。在这个阶段,能够借助 JavaScript 来创建自定义动画。
此外,还能够通过覆盖原本的 CSS 来实现自定义动画。默认的 CSS 动画是:旧页面视图的不透明度由 1 变为 0 ,新页面视图的不透明度由 0 变为 1 ,持续时长为 0.25 秒。
在动画执行完毕之后,会实现 Promise ViewTransition.finished
。
View Transitions API 的用法
通过上面的工作原理介绍,我们现在正式开始探索它的用法
Document:startViewTransition() 方法
View Transitions API 的 startViewTransition() 方法开始一个新的视图过渡,并返回一个 ViewTransition 对象来表示它。
callback: 一个在视图过渡过程中通常用于更新 DOM 的回调函数,它返回一个 Promise。 这个回调函数在 API 截取了当前页面的屏幕截图后被调用。当回调函数返回的 Promise 兑现时,视图过渡将在下一帧开始。如果回调函数返回的 Promise 拒绝,过渡将被放弃。
- ready: 在伪元素树创建并且动画即将开始时兑现
- finished: 在动画结束后兑现,此时新页面视图对用户可见且可交互
自定义过渡动画
除了默认设置的动画之外,还能够借助 CSS ,通过对伪元素的修改来自主定义过渡动画。比如,可以对动画的时间、延迟以及动画的名称等方面进行修改。
这里以本站浅色 / 暗色模式切换功能代码为例
上面这段代码中的 --click-x
、--click-y
、--end-radius
值会在点击主题切换时触发并计算,在开始时(0%),clip-path (裁剪路径)的值为一个半径为 0% 的圆形,位置由变量 --click-x 和 --click-y 决定;
在结束时(100%),clip-path 变为一个半径由变量 --end-radius 决定的圆形,位置同样由 --click-x 和 --click-y 决定。
动画效果为从点击位置扩散开的一个圆形遮罩,具体效果查看下图或点击页面右上角主题切换按钮尝试。
除了使用 CSS 来自定义动画,我们还可以使用 JS 来实现更加复杂的过渡动画。当 ViewTransition.ready 完成时,运用 document.documentElement.animate 来实现动画。
这里以 antfu 大佬的的 Blog 主题切换代码为例
使用 JS 自定义过渡动画需要覆盖默认的 CSS 动画
具体效果查看下图或前往 antfu 尝试
这样就实现了完美的使用 View Transitions API 实现了一个主题切换的功能。
总结
调用 document.startViewTransition 后,浏览器会获取当前页面状态(类似截图),进行 DOM 变化后再记录变化后的状态,然后触发过渡动画, 像透明度、位移变化等,能自定义 CSS 动画,默认是整个页面淡入淡出。
::view-transition-old 代表旧视图,::view-transition-new 代表新视图。
可给元素指定 view-transition-name 来明确具体元素变化,但同一时间页面不能有两个相同 view-transition-name 的元素,否则视图变化失效。
视图转换动画是体验增强功能,不是必要的,使用动画会拖慢页面打开或更新速度,动画时页面完全“冻结”,所以要衡量好动画时间,页面本身慢就别用。
参考
View Transitions API - Web API | MDN
Document:startViewTransition() 方法 - Web API | MDN
太丝滑了!了解一下原生的视图转换动画 View Transitions - 前端侦探 - SegmentFault 思否