2017-08-29 96 views
2

我使用React Router v4和react-transition-group v2来测试页面滑动动画。页面滑动动画与反应路由器v4和react-transition-group v2

const RouterMap =() => (
    <Router> 
    <Route render={({ location }) => 
     <TransitionGroup> 
     <CSSTransition key={location.pathname.split('/')[1]} timeout={500} classNames="pageSlider" 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" component={ Games } /> 
      </Switch> 
     </CSSTransition> 
     </TransitionGroup> 
    } /> 
    </Router> 
) 

而CSS:

.pageSlider-enter { 
    transform: translate3d(100%, 0, 0); 
} 

.pageSlider-enter.pageSlider-enter-active { 
    transform: translate3d(0, 0, 0); 
    transition: all 600ms; 
} 
.pageSlider-exit { 
    transform: translate3d(0, 0, 0); 
} 

.pageSlider-exit.pageSlider-exit-active { 
    transform: translate3d(-100%, 0, 0); 
    transition: all 600ms; 
} 

动画是波纹管:

enter image description here

正如你看到的,动画index page滑到detail page是所有权利(右向左)。但是当我点击Back图标时,我希望index page从左到右出来。

我知道,如果我更改CSS为波纹管,该网页将出来,从左至右依次为:

.pageSlider-enter { 
    transform: translate3d(-100%, 0, 0); 
} 
.pageSlider-exit.pageSlider-exit-active { 
    transform: translate3d(100%, 0, 0); 
    transition: all 600ms; 
} 

但如何在两个动画结合在一起?一般来说,每当用户点击后面的图标,动画应该是from left to right


更新:2017年8月31日

感谢@MatijaG,使用路径深度确实是一个真棒想法。我跟着它,出现了一个新问题。

function getPathDepth(location) { 
    let pathArr = (location || {}).pathname.split('/'); 
    pathArr = pathArr.filter(n => n !== ''); 
    return pathArr.length; 
} 

<Route render={({ location }) => 
    <TransitionGroup> 
    <CSSTransition 
     key={location.pathname.split('/')[1]} 
     timeout={500} 
     classNames={ getPathDepth(location) - this.state.prevDepth > 0 ? 'pageSliderLeft' : 'pageSliderRight' } 
     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 } /> // add a new route 
     <Route path="/games" component={ Games } /> 
     </Switch> 
    </CSSTransition> 
    </TransitionGroup> 
} /> 

和更新的CSS:

.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; 
} 

.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; 
} 

动画:

enter image description here

从 '/' 到 '/游戏' 是确定的,并从 '/游戏' 回'/'仍然可以(类型1:路线A - >路线B,只有2条路线)。但是,如果首先从'/'到'/游戏',然后从'/游戏'到'/游戏/ lol',则第二阶段会丢失动画(类型2:路线A→路线B→路线C ,3条或更多路线)。我们也从'/ games/lol'回到'/ games'然后回到'/',幻灯片动画与1类不一样。

任何人对这个问题有什么想法吗?

+1

我会问我什么是使用key = {位置的原因。 pathname.split('/')[1]}我认为这是你用a-> b-> c所遇到的问题。 (/ => undefined;/games => games;/games/lol => games) 这意味着/ games和/ games/lol拥有相同的关键点,所以动画不会被触发。你应该使用key = {location.key} – MatijaG

+0

@MatijaG,是的,你是对的。这是我的错误。我使用'key = {location.pathname.split('/')[1]}'因为HashRouter。 – jason

+0

@MatijaG,当我深入了解这个问题时,我发现还有一些其他问题。所以我问另一个问题:https://stackoverflow.com/questions/45978263/dynamic-page-sliding-animation-with-react-router-v4-and-react-transition-group-v。如果你有一些时间,我真的希望我能在那里得到你的帮助。无论如何,非常感谢。 – jason

回答

4

那么主要问题是,即使在你的问题中,你没有指定应用程序应该如何知道使用哪个方向。

你可以这样做的一种方法是使用路径深度/长度:如果你正在导航的路径比当前路径“更深”,则从右向左过渡,但是如果它从左向右过渡更浅?

的另一个问题是,路由器只给你你要的位置,所以你应该保存以前的位置(或深度),这样你就可以把它比作。

之后,仅仅是一个CSS类名之间切换事, 东西沿着这条线:

import React from 'common/react' 
import { withRouter, Route, Switch } from 'react-router' 

function getPathDepth (location) { 
    return (location || {}).pathname.split('/').length 
} 
class RouterMap extends React.PureComponent { 
    constructor (props, context) { 
     super(props, context) 
     this.state = { 
      prevDepth: getPathDepth(props.location), 
     } 
    } 

    componentWillReceiveProps() { 
     this.setState({ prevDepth: getPathDepth(this.props.location) }) 
    } 
    render() { 

     return (
      <Router> 
       <Route render={ ({ location }) => 
        (<TransitionGroup> 
         <CSSTransition 
          key={ location.pathname.split('/')[1] } 
          timeout={ 500 } 
          classNames={ getPathDepth(location) - this.state.prevDepth ? 'pageSliderLeft' : 'pageSliderRight' } 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' component={ Games } /> 
          </Switch> 
         </CSSTransition> 
        </TransitionGroup>) 
       } 
       /> 
      </Router> 
     ) 
    } 
} 

export default withRouter(RouterMap) 

Codepen例如:https://codepen.io/matijag/pen/ayXpGr?editors=0110

+0

非常感谢你,使用路径深度真的是一个很棒的想法。我跟着你,出现了一个新问题。该动画仅适用于两条路线(**路线A - >路线B **)。我对此感到困惑,我更新了问题描述以获取更多信息。 – jason