📖 文章摘要
基于导航方向差异化页面过渡动画的设计思路和技术实现。从导航栏数字顺序推导前进/后退/相同页面三种滑入/滑出行为,附避坑记录和手感调优参数。
页面过渡动画设计
概述
本博客实现了基于导航方向的差异化页面过渡动画系统,根据用户点击的导航位置动态决定滑动方向,让页面切换手感顺滑自然。
设计理念
页面切换动画的核心原则:导航方向决定动画方向。
将 7 个主导航标签映射为数字顺序:
首页(0) → 分类(1) → 标签(2) → 网盘(3) → 图床(4) → 碎念(5) → 关于(6)
方向规则
| 导航方向 | 旧页行为 | 新页行为 | 过渡名 |
|---|---|---|---|
| 前进(小→大) | 向左滑出 | 从右滑入 | slide-left |
| 后退(大→小) | 向右滑出 | 从左滑入 | slide-right |
| 相同页面(→自身) | 向下滑出 | 从上滑入 | slide-down |
物理隐喻
想象一把展开的纸扇:
- 向右翻(前进):当前页向左离开,下一页从右侧出现
- 向左翻(后退):当前页向右离开,上一页从左侧出现
- 点击当前页:模拟下拉刷新效果,页面向下离开再从上进入
技术实现
架构
default.vue 的 <main>
└─ <Transition :name="transitionName" mode="out-in">
└─ <div :key="$route.path">
└─ <slot /> ← 页面内容
- Transition 层:布局文件
default.vue中手动包裹<slot />,不依赖 Nuxt 内置过渡系统 - 方向判断:
watch(() => route.path)监听路由变化,按导航路径数组索引比较方向 - 强制触发:
$route.path作为 key,路由变化时 Vue 销毁重建 wrapper,触发动画
关键代码
const navPaths = ['/', '/categories', '/tags', '/pan', '/uploads', '/moments', '/about']
watch(() => route.path, (newPath, oldPath) => {
const newIndex = navPaths.indexOf(newPath)
const oldIndex = navPaths.indexOf(oldPath)
// ... 判断方向设置 transitionName
})
CSS 动画
进入/离开的过渡时序分离,提升流畅感:
/* 进入:opacity 先到位(0.2s),transform 慢慢滑完(0.35s) */
.slide-left-enter-active {
transition: transform 0.35s cubic-bezier(0.2, 0, 0, 1),
opacity 0.2s cubic-bezier(0.2, 0, 0, 1);
}
/* 离开:快速消失(0.25s),不让用户等着看旧页退场 */
.slide-left-leave-active {
transition: transform 0.25s cubic-bezier(0.2, 0, 0, 1),
opacity 0.15s ease;
}
关键参数:
| 参数 | 值 | 作用 |
|---|---|---|
| 平移距离 | 100px | 视觉感知明显,不会觉得"动了但没完全动" |
| 进入缓动 | cubic-bezier(0.2, 0, 0, 1) |
起步快、末段干脆停住 |
| 进入时长 | transform 0.35s / opacity 0.2s | 内容快速可读,动作完整展示 |
| 离开时长 | transform 0.25s / opacity 0.15s | 旧页快出,不留恋 |
避坑记录
<NuxtPage />不能直接包在<Transition>里:Nuxt 内部使用<RouterView>渲染页面,路由切换时会产出占位注释节点,导致Transition报错 "non-element root node"。正确做法是在 layout 层包裹<slot />。中间件设置
to.meta.pageTransition可能被忽略:取决于 Nuxt 版本和pageTransition的配置时机。最可靠的方式是直接操作 DOM 级别的<Transition>。<slot />需要 key 才能触发过渡:Vue 的<Transition>检测子元素 identity 变化来播放动画。用$route.path作为 key,确保路由变化时组件被销毁重建。
滑入手感对比
| 版本 | 描述 | 评价 |
|---|---|---|
| 初始版 | fadeIn 0.5s ease 简单淡入 |
太单调 |
| v2(config 版) | pageTransition + slide 40px 0.35s |
几乎看不出滑动 |
| v3(现在) | 方向差异化 + 100px 大幅滑入 + 变速分离 | 爽 |
总结
这套过渡系统:
- 方向感知:前进/后退/相同页面三种不同动画,直觉匹配导航行为
- 手感优先:opacity 和 transform 分离控制,内容快速可读 + 动作完整展示
- 轻量实现:纯 Vue Transition,不依赖 Nuxt 内部系统,少踩坑
- 统一风格:缓动曲线与毛玻璃 hover 效果同源,全站交互语言一致
最后更新:2026年6月29日CC BY-NC-SA 4.0
评论
暂无评论,来写第一条吧
