如何基于react-spring useTransition实现路由切换时的左右方向过渡动画?
动态切换React Router路由过渡动画方向的实现方案
嘿,我来帮你搞定这个路由过渡方向的问题!无论是在你自己的项目里调整动画方向,还是修改你提到的示例让Profile页面从右到左进入,都可以通过跟踪路由导航状态/路径变化来实现,下面一步步来:
一、核心思路:判断路由导航的方向
要切换动画方向,关键是要知道当前是「前进到新路由」还是「后退到旧路由」,或者针对特定路由自定义方向,然后根据这个方向调整动画的transform参数(比如translateX的正负值)。
二、在你的项目中实现通用动态方向过渡
以React Router v5 + react-spring为例(v6的思路类似,只是API略有不同):
1. 跟踪导航动作或路径变化
import { useHistory, useLocation } from 'react-router-dom'; import { useTransition, animated } from 'react-spring'; import { useState, useEffect } from 'react'; function App() { const history = useHistory(); const location = useLocation(); // 用history.action判断是前进(PUSH)还是后退(POP) const isBackNavigation = history.action === 'POP'; // 跟踪前后路径,用于自定义路由方向规则 const [prevPath, setPrevPath] = useState(location.pathname); useEffect(() => { setPrevPath(location.pathname); }, [location.pathname]); // ... 后续代码 }
2. 根据方向设置动画参数
把方向判断结果传入useTransition,动态调整进入/离开的位移方向:
// 自定义方向判断逻辑,比如针对特定路由设置方向 const getAnimationDirection = () => { // 示例:从首页进入Profile时强制用右到左,其他前进用左到右,后退用右到左 if (prevPath === '/' && location.pathname === '/profile') { return 'right-to-left'; } return isBackNavigation ? 'right-to-left' : 'left-to-right'; }; const direction = getAnimationDirection(); const transitions = useTransition(location, { from: { opacity: 0, transform: direction === 'right-to-left' ? 'translateX(100%)' : 'translateX(-100%)' }, enter: { opacity: 1, transform: 'translateX(0)' }, leave: { opacity: 0, transform: direction === 'right-to-left' ? 'translateX(-100%)' : 'translateX(100%)' }, }); // 渲染过渡组件 return transitions((style, item) => ( <animated.div style={style} className="page-container"> <Switch location={item}> <Route exact path="/" component={Home} /> <Route path="/profile" component={Profile} /> {/* 其他路由 */} </Switch> </animated.div> ));
三、修改目标示例,让Profile页面从右到左进入
针对那个使用react-spring的示例,我们只需要在原代码基础上添加路径跟踪和方向判断即可:
1. 添加路径跟踪状态
在示例的主组件中,添加状态保存上一个路径:
import { useState, useEffect } from 'react'; import { useLocation } from 'react-router-dom'; // ... 其他导入 function App() { const location = useLocation(); const [prevPath, setPrevPath] = useState(location.pathname); useEffect(() => { setPrevPath(location.pathname); }, [location.pathname]); // ... 原代码 }
2. 修改useTransition的动画参数
根据当前路径和上一个路径的关系,设置进入方向:
// 判断是否是从首页进入Profile const isEnteringProfile = prevPath === '/' && location.pathname === '/profile'; // 判断是否是从Profile回到首页 const isLeavingProfile = prevPath === '/profile' && location.pathname === '/'; const transitions = useTransition(location, { from: { opacity: 0, transform: isEnteringProfile ? 'translateX(100%)' : 'translateX(-100%)' }, enter: { opacity: 1, transform: 'translateX(0)' }, leave: { opacity: 0, transform: isLeavingProfile ? 'translateX(100%)' : 'translateX(-100%)' }, });
这样修改后,当你点击示例中的Profile链接时,页面会从右侧滑入(右到左的过渡),从Profile回到首页时则从左侧滑出,完美符合你的需求!
补充:React Router v6的适配
如果你的项目用的是v6,只需要把useHistory换成useNavigate,同时Switch换成Routes,核心的方向判断逻辑是一样的:
import { useLocation, useNavigate } from 'react-router-dom'; // 在组件中 const navigate = useNavigate(); // v6中可以通过监听location变化来判断,或者用第三方库辅助跟踪历史动作
内容的提问来源于stack exchange,提问作者Rodrigo
相关产品推荐
相关产品推荐

