做 Web 开发,最让我们羡慕原生 Native App 的一点,就是它们那种如丝般顺滑的页面转场动画。点击列表中的小图,图片能够自然地放大、变形成为详情页的大图;点击返回,图片又优雅地缩回原位。
在 Web 领域,我们过去称之为 Hero Animation。传统的实现方式极其繁琐,需要手动计算元素的 getBoundingClientRect,推导 scale 和 translate 值,还要小心翼翼地处理图层层级,代码复杂且容易出错。
但现在,情况完全不同了。Chrome 和 Safari 早已全面支持 View Transitions API。它将所有复杂的数学计算都交给了浏览器底层引擎,我们开发者只需要清晰地告诉它:“转场起点的元素是哪个,终点的元素又是哪个”。
今天,我们就来深入实践这个强大的原生 API。
01. Hello World:一行代码实现淡入淡出
在以往,为 Vue 应用添加路由切换动画,我们需要使用 <Transition> 组件包裹,并编写一系列的 CSS 过渡或动画规则。
而现在,你只需要在触发视图更新的地方,用一行代码将其包裹起来:
// 当你需要更新 DOM(例如切换路由、切换组件状态)时
document.startViewTransition(() => {
// 这里放置你原本更新 DOM 的逻辑
// 例如:router.push('/detail') 或者修改响应式数据触发 v-if/v-show
updateTheDOMSomehow();
});
那么,这行代码背后发生了什么呢?
浏览器会自动捕获当前页面的状态(截图),执行你提供的 DOM 更新回调,然后再捕获新页面的状态(截图)。最后,它会在新旧两张截图之间,自动创建一个 Cross-fade(交叉淡入淡出) 的平滑过渡效果。
仅仅添加这一行代码,你的网页瞬间就能拥有一种高级、流畅的质感。如果你想深入了解现代前端开发中的其他高效实践,可以关注 云栈社区 的相关讨论。
02. 核心魔法:共享元素过渡 (Hero Animation)
这是 View Transitions API 最引人注目的功能。
典型场景:列表页中有一个用户小头像,点击后进入详情页,详情页会显示一个更大的头像。我们的目标是让这个小头像能够平滑地“飞”过去,并逐渐放大成为详情页的大头像。
如何实现?你只需要为这两个处于不同页面(或不同状态)的元素,设置相同的 view-transition-name CSS 属性。
列表页 CSS:
.list-item-img {
/* 为当前被点击的图片赋予一个唯一的过渡标识名 */
view-transition-name: avatar-transition;
contain: layout; /* 最佳实践:启用布局隔离以优化性能 */
}
详情页 CSS:
.detail-header-img {
/* 这个标识名必须与列表页的保持一致! */
view-transition-name: avatar-transition;
}
JS 调用逻辑:
document.startViewTransition(async () => {
// 执行跳转到详情页的逻辑
await navigateToDetail();
});
接下来,奇迹发生了。
浏览器会发现,在过渡前后的两个 DOM 状态中,都存在一个名为 avatar-transition 的元素。它会自动计算这两个元素之间精确的位置差异和尺寸差异,并自动生成一段平滑的位移与缩放动画。我们完全不需要编写任何 JavaScript 来计算坐标和比例,这对于实现复杂的 CSS动画 效果是一个巨大的解放。
03. 进阶:与 Vue Router 集成
在现代 Vue 项目中,我们可以编写一个通用的路由守卫,来为所有页面跳转启用 View Transitions。
router.beforeResolve((to, from, next) => {
// 如果浏览器不支持该 API,则直接降级进行普通跳转
if (!document.startViewTransition) {
next();
return;
}
// 拦截路由跳转,启用视图过渡
document.startViewTransition(async () => {
next(); // 执行路由更新,从而触发 DOM 变更
// 等待 DOM 更新完成(Vue 内部会处理 nextTick)
});
});
这里有一个重要的注意事项:view-transition-name 在同一时间必须是页面内唯一的。
这意味着,在列表页中,你不能给所有头像图片都设置同一个名字(如 avatar)。正确的做法是动态设置:
- 点击时:仅为当前被点击的那个图片元素设置
view-transition-name: active-avatar。
- 跳转后:在详情页的目标大图元素上设置相同的
view-transition-name: active-avatar。
- 动画结束后:移除这个
view-transition-name,防止它对后续的样式或交互造成污染。
这种动态管理状态的方式,在复杂的 前端框架/工程化 应用中非常常见。
04. 自定义动画曲线与方向
默认的淡入淡出效果不能满足所有场景?如果你想实现诸如“从右侧滑入”这样的效果,完全可以!
View Transitions API 在过渡期间会创建一组特殊的伪元素供我们控制:
::view-transition-old(root):代表旧页面状态的截图层。
::view-transition-new(root):代表新页面状态的截图层。
以下 CSS 可以实现一个经典的“左滑进入,右滑退出”效果:
/* 旧页面向右滑出屏幕 */
::view-transition-old(root) {
animation: slide-out-right 0.3s ease-out;
}
/* 新页面从左侧滑入屏幕 */
::view-transition-new(root) {
animation: slide-in-left 0.3s ease-out;
}
@keyframes slide-out-right {
to { transform: translateX(100%); }
}
@keyframes slide-in-left {
from { transform: translateX(-100%); }
}
你可以通过定义不同的 @keyframes 来创造任何你想要的转场动画,例如缩放、旋转或组合效果,完全掌控转场的视觉表现。
结语
View Transitions API 的出现,标志着 Web 应用在用户体验 (UX) 层面真正具备了追平甚至超越原生应用的潜力。它无需开发者精通图形学或复杂的数学矩阵计算,本质上,你只需要懂得如何编写 CSS,就能创造出令人惊艳的过渡效果。
花点时间,将这项技术应用到你的个人博客或下一个项目中,那份肉眼可见的“高级感”和流畅度,将是提升用户满意度的关键一步。