2017-08-29 98 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