I asked a question before about how to realize the page sliding animation: page sliding animation with React Router v4 and react-transition-group v2.
After that, I got a more difficult problem.
function getPathDepth(location) {
let pathArr = (location || {}).pathname.split('/');
pathArr = pathArr.filter(n => n !== '');
return pathArr.length;
}
class Routers extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
prevDepth: getPathDepth(props.location)
};
}
componentWillReceiveProps() {
this.setState({ prevDepth: getPathDepth(this.props.location) });
}
render() {
return (
<Route render={({ location }) => {
return (
<TransitionGroup>
<CSSTransition
key={location.key}
timeout={500}
classNames={ getPathDepth(location) - this.state.prevDepth > 0 ? 'pageSliderLeft' : 'pageSliderRight' }
classNames={classNames}
mountOnEnter={true}
unmountOnExit={true}
>
<Switch location={location}>
<Route path="/" exact component={ Index } />
<Route path="/comments" component={ Comments } />
<Route path="/opinions" component={ Opinions } />
<Route path="/games/lol" component={ LOL } />
<Route path="/games/dota" component={ DotA } />
<Route path="/games" component={ Games } />
</Switch>
</CSSTransition>
</TransitionGroup>
);
}} />
)
}
}
const WrapRouters = withRouter(Routers);
export default function RouterMap() {
return (
<BrowserRouter>
<WrapRouters />
</BrowserRouter>
);
}
The CSS:
.pageSliderRight-enter {
transform: translate3d(-100%, 0, 0);
}
.pageSliderRight-enter.pageSliderRight-enter-active {
transform: translate3d(0, 0, 0);
transition: all 600ms;
}
.pageSliderRight-exit {
transform: translate3d(0, 0, 0);
}
.pageSliderRight-exit.pageSliderRight-exit-active {
transform: translate3d(-100%, 0, 0);
transition: all 600ms;
}
.pageSliderLeft-enter {
transform: translate3d(100%, 0, 0);
}
.pageSliderLeft-enter.pageSliderLeft-enter-active {
transform: translate3d(0, 0, 0);
transition: all 600ms;
}
.pageSliderLeft-exit {
transform: translate3d(0, 0, 0);
}
.pageSliderLeft-exit.pageSliderLeft-exit-active {
transform: translate3d(100%, 0, 0);
transition: all 600ms;
}
The animation:
If only sliding from '/' to '/games' and then from '/games' back to '/', everything is fine. But with more routes, it gets complicated.
When from '/' to '/games', the Games's exit animation is specified, not changeable. But obviously, it should be dynamic.
- '/' --> '/games' && '/games' --> '/', exit animation should be 'slide to right'
- '/' --> '/games' && '/games' --> '/games/lol', exit animation should be 'slide to left'
More generally, when getting deeper route, the sliding animation should be 'slide to left'. Otherwise, the animation should be 'slide to right'.
How to set the animation dynamically?