使用React Router v4和react-transition-group v2的动态页面滑动动画

时间:2017-08-31 09:42:29

标签: react-router react-transition-group

之前我问了一个关于如何实现页面滑动动画的问题:page sliding animation with React Router v4 and react-transition-group v2

之后,我遇到了一个更难的问题。

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

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

动画:

enter image description here

如果仅从&#39; /&#39;滑动到&#39; /游戏&#39;然后从&#39; / games&#39;回到&#39; /&#39;,一切都很好。但是由于路线越来越多,它就变得复杂了。

来自&#39; /&#39;对于游戏&#39;,游戏的退出动画是指定的,不可更改。但显然,它应该是动态的。

  • &#39; /&#39; - &GT; &#39; /游戏&#39; &安培;&安培; &#39; /游戏&#39; - &GT; &#39; /&#39;,退出动画 应向右滑动
  • &#39; /&#39; - &GT; &#39; /游戏&#39; &安培;&安培; &#39; /游戏&#39; - &GT; &#39; / games / lol&#39;,退出动画 应向左滑动&#39;

更一般地说,当获得更深的路线时,滑动动画应该向左滑动&#39;。否则,动画应该向右滑动

如何动态设置动画?

1 个答案:

答案 0 :(得分:1)

正如我在评论中已经提到的那样,我认为问题在于现有元素已经过时了。为了解决这个问题,我认为你必须使用子工厂并在退出之前用新的道具克隆元素。

或者,可以通过仅执行输入动画来简化动画(并且它还应该在移动设备上具有更好的性能),并忽略退出动画。把它想象成一堆卡片。

enter image description here

这样的事情: CSS:

.pageSlider-exit  > .page{
    z-index:1;
}
.pageSlider-enter > .page{
    z-index:10;
}
.pageSlider-enter.left > .page{
    transform: translate3d(100%, 0, 0);
}

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

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

完整示例: https://codepen.io/anon/pen/yoGqxQ