精华内容
下载资源
问答
  • React老虎过渡 页面转换。 在导航过程中以编程方式对路线进行动画处理。 该模块无需在内定义动画,而在<Link />内定义动画,从而可以通过不同的转换轻松到达和保留相同的url。 文献资料 特征 动态创建动态...
  • react项目当中,我们一般都会选用react-router来管理路由,但是react-router却并没有提供相应的转场动画功能,而是非常生硬的直接替换掉组件。一定程度上来说,体验并不是那么友好。 为了在react中实现动画效果,...

    原文地址

    1. Introduction

    在日常开发中,页面切换时的转场动画是比较基础的一个场景。在react项目当中,我们一般都会选用react-router来管理路由,但是react-router却并没有提供相应的转场动画功能,而是非常生硬的直接替换掉组件。一定程度上来说,体验并不是那么友好。

    为了在react中实现动画效果,其实我们有很多的选择,比如:react-transition-groupreact-motionAnimated等等。但是,由于react-transition-group给元素添加的enter,enter-active,exit,exit-active这一系列勾子,简直就是为我们的页面入场离场而设计的。基于此,本文选择react-transition-group来实现动画效果。

    接下来,本文就将结合两者提供一个实现路由转场动画的思路,权当抛砖引玉~

    2. Requirements

    我们先明确要完成的转场动画是什么效果。如下图所示:

    3. react-router

    首先,我们先简要介绍下react-router的基本用法(详细看官网介绍)。

    这里我们会用到react-router提供的BrowserRouterSwitchRoute三个组件。

    • BrowserRouter:以html5提供的history api形式实现的路由(还有一种hash形式实现的路由)。
    • Switch:多个Route组件同时匹配时,默认都会显示,但是被Switch包裹起来的Route组件只会显示第一个被匹配上的路由。
    • Route:路由组件,path指定匹配的路由,component指定路由匹配时展示的组件。
    // src/App1/index.js
    export default class App1 extends React.PureComponent {
      render() {
        return (
          <BrowserRouter>
            <Switch>
              <Route exact path={'/'} component={HomePage}/>
              <Route exact path={'/about'} component={AboutPage}/>
              <Route exact path={'/list'} component={ListPage}/>
              <Route exact path={'/detail'} component={DetailPage}/>
            </Switch>
          </BrowserRouter>
        );
      }
    }
    复制代码

    如上所示,这是路由关键的实现部分。我们一共创建了首页关于页列表页详情页这四个页面。跳转关系为:

    1. 首页 ↔ 关于页
    2. 首页 ↔ 列表页 ↔ 详情页

    来看下目前默认的路由切换效果:

    4. react-transition-group

    从上面的效果图中,我们可以看到react-router在路由切换时完全没有过渡效果,而是直接替换的,显得非常生硬。

    正所谓工欲善其事,必先利其器,在介绍实现转场动画之前,我们得先学习如何使用react-transition-group。基于此,接下来就将对其提供的CSSTransition和TransitionGroup这两个组件展开简要介绍。

    4.1 CSSTransition

    CSSTransition是react-transition-group提供的一个组件,这里简单介绍下其工作原理。

    When the in prop is set to true, the child component will first receive the class example-enter, then the example-enter-active will be added in the next tick. CSSTransition forces a reflow between before adding the example-enter-active. This is an important trick because it allows us to transition between example-enter and example-enter-active even though they were added immediately one after another. Most notably, this is what makes it possible for us to animate appearance.

    这是来自官网上的一段描述,意思是当CSSTransition的in属性置为true时,CSSTransition首先会给其子组件加上xxx-enter的class,然后在下个tick时马上加上xxx-enter-active的class。所以我们可以利用这一点,通过css的transition属性,让元素在两个状态之间平滑过渡,从而得到相应的动画效果。

    相反地,当in属性置为false时,CSSTransition会给子组件加上xxx-exit和xxx-exit-active的class。(更多详细介绍可以戳官网查看)

    基于以上两点,我们是不是只要事先写好class对应的css样式即可?可以做个小demo试试,如下代码所示:

    // src/App2/index.js
    export default class App2 extends React.PureComponent {
    
      state = {show: true};
    
      onToggle = () => this.setState({show: !this.state.show});
    
      render() {
        const {show} = this.state;
        return (
          <div className={'container'}>
            <div className={'square-wrapper'}>
              <CSSTransition
                in={show}
                timeout={500}
                classNames={'fade'}
                unmountOnExit={true}
              >
                <div className={'square'} />
              </CSSTransition>
            </div>
            <Button onClick={this.onToggle}>toggle</Button>
          </div>
        );
      }
    }
    复制代码
    /* src/App2/index.css */
    .fade-enter {
      opacity: 0;
      transform: translateX(100%);
    }
    
    .fade-enter-active {
      opacity: 1;
      transform: translateX(0);
      transition: all 500ms;
    }
    
    .fade-exit {
      opacity: 1;
      transform: translateX(0);
    }
    
    .fade-exit-active {
      opacity: 0;
      transform: translateX(-100%);
      transition: all 500ms;
    }
    复制代码

    来看看效果,是不是和页面的入场离场效果有点相似?

    4.2 TransitionGroup

    用CSSTransition来处理动画固然很方便,但是直接用来管理多个页面的动画还是略显单薄。为此我们再来介绍react-transition-group提供的TransitionGroup这个组件。

    The component manages a set of transition components ( and ) in a list. Like with the transition components, is a state machine for managing the mounting and unmounting of components over time.

    如官网介绍,TransitionGroup组件就是用来管理一堆节点mounting和unmounting过程的组件,非常适合处理我们这里多个页面的情况。这么介绍似乎有点难懂,那就让我们来看段代码,解释下TransitionGroup的工作原理。

    // src/App3/index.js
    export default class App3 extends React.PureComponent {
    
      state = {num: 0};
    
      onToggle = () => this.setState({num: (this.state.num + 1) % 2});
    
      render() {
        const {num} = this.state;
        return (
          <div className={'container'}>
            <TransitionGroup className={'square-wrapper'}>
              <CSSTransition
                key={num}
                timeout={500}
                classNames={'fade'}
              >
                <div className={'square'}>{num}</div>
              </CSSTransition>
            </TransitionGroup>
            <Button onClick={this.onToggle}>toggle</Button>
          </div>
        );
      }
    }
    复制代码

    我们先来看效果,然后再做解释:

    对比App3和App2的代码,我们可以发现这次CSSTransition没有in属性了,而是用到了key属性。但是为什么仍然可以正常工作呢?

    在回答这个问题之前,我们先来思考一个问题:

    由于react的dom diff机制用到了key属性,如果前后两次key不同,react会卸载旧节点,挂载新节点。那么在上面的代码中,由于key变了,旧节点难道不是应该立马消失,但是为什么我们还能看到它淡出的动画过程呢?

    关键就出在TransitionGroup身上,因为它在感知到其children变化时,会先保存住即将要被移除的节点,而在其动画结束时才会真正移除该节点。

    所以在上面的例子中,当我们按下toggle按钮时,变化的过程可以这样理解:

    <TransitionGroup>
      <div>0</div>
    </TransitionGroup>
    
    ⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️
    
    <TransitionGroup>
      <div>0</div>
      <div>1</div>
    </TransitionGroup>
    
    ⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️
    
    <TransitionGroup>
      <div>1</div>
    </TransitionGroup>
    复制代码

    如上所解释,我们完全可以巧妙地借用key值的变化来让TransitionGroup来接管我们在过渡时的页面创建和销毁工作,而仅仅需要关注如何选择合适的key值和需要什么样css样式来实现动画效果就可以了。

    5. Page transition animation

    基于前文对react-router和react-transition-group的介绍,我们已经掌握了基础,接下来就可以将两者结合起来做页面切换的转场动画了。

    在上一小节的末尾有提到,用了TransitionGroup之后我们的问题变成如何选择合适的key值。那么在路由系统中,什么作为key值比较合适呢?

    既然我们是在页面切换的时候触发转场动画,自然是跟路由相关的值作为key值合适了。而react-router中的location对象就有一个key属性,它会随着浏览器中的地址发生变化而变化。然而,在实际场景中似乎并不适合,因为query参数或者hash变化也会导致location.key发生变化,但往往这些场景下并不需要触发转场动画。

    因此,个人觉得key值的选取还是得根据不同的项目而视。大部分情况下,还是推荐用location.pathname作为key值比较合适,因为它恰是我们不同页面的路由。

    说了这么多,还是看看具体的代码是如何将react-transition-group应用到react-router上的吧:

    // src/App4/index.js
    const Routes = withRouter(({location}) => (
      <TransitionGroup className={'router-wrapper'}>
        <CSSTransition
          timeout={5000}
          classNames={'fade'}
          key={location.pathname}
        >
          <Switch location={location}>
            <Route exact path={'/'} component={HomePage} />
            <Route exact path={'/about'} component={AboutPage} />
            <Route exact path={'/list'} component={ListPage} />
            <Route exact path={'/detail'} component={DetailPage} />
          </Switch>
        </CSSTransition>
      </TransitionGroup>
    ));
    
    export default class App4 extends React.PureComponent {
      render() {
        return (
          <BrowserRouter>
            <Routes/>
          </BrowserRouter>
        );
      }
    }
    复制代码

    这是效果:

    App4的代码思路跟App3大致相同,只是将原来的div换成了Switch组件,而且还用到了withRouter。

    withRouter是react-router提供的一个高阶组件,可以为你的组件提供location,history等对象。因为我们这里要用location.pathname作为CSSTransition的key值,所以用到了它。

    另外,这里有一个坑,就是Switch的location属性。

    A location object to be used for matching children elements instead of the current history location (usually the current browser URL).

    这是官网中的描述,意思就是Switch组件会用这个对象来匹配其children中的路由,而且默认用的就是当前浏览器的url。如果在上面的例子中我们不给它指定,那么在转场动画中会发生很奇怪的现象,就是同时有两个相同的节点在移动。。。就像下面这样:

    这是因为TransitionGroup组件虽然会保留即将被remove的Switch节点,但是当location变化时,旧的Switch节点会用变化后的location去匹配其children中的路由。由于location都是最新的,所以两个Switch匹配出来的页面是相同的。好在我们可以改变Switch的location属性,如上述代码所示,这样它就不会总是用当前的location匹配了。

    6. Page dynamic transition animation

    虽然前文用react-transition-group和react-router实现了一个简单的转场动画,但是却存在一个严重的问题。仔细观察上一小节的示意图,不难发现我们的进入下个页面的动画效果是符合预期的,但是后退的动画效果是什么鬼。。。明明应该是上个页面从左侧淡入,当前页面从右侧淡出。但是为什么却变成当前页面从左侧淡出,下个页面从右侧淡入,跟进入下个页面的效果是一样的。其实错误的原因很简单:

    首先,我们把路由改变分成forward和back两种操作。在forward操作时,当前页面的exit效果是向左淡出;在back操作时,当前页面的exit效果是向右淡出。所以我们只用fade-exit和fade-exit-active这两个class,很显然,得到的动画效果肯定是一致的。

    因此,解决方案也很简单,我们用两套class来分别管理forward和back操作时的动画效果就可以了。

    /* src/App5/index.css */
    
    /* 路由前进时的入场/离场动画 */
    .forward-enter {
      opacity: 0;
      transform: translateX(100%);
    }
    
    .forward-enter-active {
      opacity: 1;
      transform: translateX(0);
      transition: all 500ms;
    }
    
    .forward-exit {
      opacity: 1;
      transform: translateX(0);
    }
    
    .forward-exit-active {
      opacity: 0;
      transform: translateX(-100%);
      transition: all 500ms;
    }
    
    /* 路由后退时的入场/离场动画 */
    .back-enter {
      opacity: 0;
      transform: translateX(-100%);
    }
    
    .back-enter-active {
      opacity: 1;
      transform: translateX(0);
      transition: all 500ms;
    }
    
    .back-exit {
      opacity: 1;
      transform: translateX(0);
    }
    
    .back-exit-active {
      opacity: 0;
      transform: translate(100%);
      transition: all 500ms;
    }
    复制代码

    不过光有css的支持还不行,我们还得在不同的路由操作时加上合适的class才行。那么问题又来了,在TransitionGroup的管理下,一旦某个组件挂载后,其exit动画其实就已经确定了,可以看官网上的这个issue。也就是说,就算我们动态地给CSSTransition添加不同的ClassNames属性来指定动画效果,但其实是无效的。

    解决方案其实在那个issue的下面就给出了,我们可以借助TransitionGroup的ChildFactory属性以及React.cloneElement方法来强行覆盖其className。比如:

    <TransitionGroup childFactory={child => React.cloneElement(child, {
      classNames: 'your-animation-class-name'
    })}>
      <CSSTransition>
        ...
      </CSSTransition>
    </TransitionGroup>
    复制代码

    上述几个问题都解决之后,剩下的问题就是如何选择合适的动画class了。而这个问题的实质在于如何判断当前路由的改变是forward还是back操作了。好在react-router已经贴心地给我们准备好了,其提供的history对象有一个action属性,代表当前路由改变的类型,其值是'PUSH' | 'POP' | 'REPLACE'。所以,我们再调整下代码:

    // src/App5/index.js
    const ANIMATION_MAP = {
      PUSH: 'forward',
      POP: 'back'
    }
    
    const Routes = withRouter(({location, history}) => (
      <TransitionGroup
        className={'router-wrapper'}
        childFactory={child => React.cloneElement(
          child,
          {classNames: ANIMATION_MAP[history.action]}
        )}
      >
        <CSSTransition
          timeout={500}
          key={location.pathname}
        >
          <Switch location={location}>
            <Route exact path={'/'} component={HomePage} />
            <Route exact path={'/about'} component={AboutPage} />
            <Route exact path={'/list'} component={ListPage} />
            <Route exact path={'/detail'} component={DetailPage} />
          </Switch>
        </CSSTransition>
      </TransitionGroup>
    ));
    复制代码

    再来看下修改之后的动画效果:

    7. Optimize

    其实,本节的内容算不上优化,转场动画的思路到这里基本上已经结束了,你可以脑洞大开,通过添加css来实现更炫酷的转场动画。不过,这里还是想再讲下如何将我们的路由写得更配置化(个人喜好,不喜勿喷)。

    我们知道,react-router在升级v4的时候,做了一次大改版。更加推崇动态路由,而非静态路由。不过具体问题具体分析,在一些项目中个人还是喜欢将路由集中化管理,就上面的例子而言希望能有一个RouteConfig,就像下面这样:

    // src/App6/RouteConfig.js
    export const RouterConfig = [
      {
        path: '/',
        component: HomePage
      },
      {
        path: '/about',
        component: AboutPage,
        sceneConfig: {
          enter: 'from-bottom',
          exit: 'to-bottom'
        }
      },
      {
        path: '/list',
        component: ListPage,
        sceneConfig: {
          enter: 'from-right',
          exit: 'to-right'
        }
      },
      {
        path: '/detail',
        component: DetailPage,
        sceneConfig: {
          enter: 'from-right',
          exit: 'to-right'
        }
      }
    ];
    复制代码

    透过上面的RouterConfig,我们可以清晰的知道每个页面所对应的组件是哪个,而且还可以知道其转场动画效果是什么,比如关于页面是从底部进入页面的,列表页详情页都是从右侧进入页面的。总而言之,我们通过这个静态路由配置表可以直接获取到很多有用的信息,而不需要深入到代码中去获取信息。

    那么,对于上面的这个需求,我们对应的路由代码需要如何调整呢?请看下面:

    // src/App6/index.js
    const DEFAULT_SCENE_CONFIG = {
      enter: 'from-right',
      exit: 'to-exit'
    };
    
    const getSceneConfig = location => {
      const matchedRoute = RouterConfig.find(config => new RegExp(`^${config.path}$`).test(location.pathname));
      return (matchedRoute && matchedRoute.sceneConfig) || DEFAULT_SCENE_CONFIG;
    };
    
    let oldLocation = null;
    const Routes = withRouter(({location, history}) => {
    
      // 转场动画应该都是采用当前页面的sceneConfig,所以:
      // push操作时,用新location匹配的路由sceneConfig
      // pop操作时,用旧location匹配的路由sceneConfig
      let classNames = '';
      if(history.action === 'PUSH') {
        classNames = 'forward-' + getSceneConfig(location).enter;
      } else if(history.action === 'POP' && oldLocation) {
        classNames = 'back-' + getSceneConfig(oldLocation).exit;
      }
    
      // 更新旧location
      oldLocation = location;
    
      return (
        <TransitionGroup
          className={'router-wrapper'}
          childFactory={child => React.cloneElement(child, {classNames})}
        >
          <CSSTransition timeout={500} key={location.pathname}>
            <Switch location={location}>
              {RouterConfig.map((config, index) => (
                <Route exact key={index} {...config}/>
              ))}
            </Switch>
          </CSSTransition>
        </TransitionGroup>
      );
    });
    复制代码

    由于css代码有点多,这里就不贴了,不过无非就是相应的转场动画配置,完整的代码可以看github上的仓库。我们来看下目前的效果:

    8. Summarize

    本文先简单介绍了react-router和react-transition-group的基本使用方法;其中还分析了利用CSSTransition和TransitionGroup制作动画的工作原理;接着又将react-router和react-transition-group两者结合在一起完成一次转场动画的尝试;并利用TransitionGroup的childFactory属性解决了动态转场动画的问题;最后将路由配置化,实现路由的统一管理以及动画的配置化,完成一次react-router + react-transition-group实现转场动画的探索。

    9. Reference

    1. A shallow dive into router v4 animated transitions
    2. Dynamic transitions with react router and react transition group
    3. Issue#182 of react-transition-group
    4. StackOverflow: react-transition-group and react clone element do not send updated props

    本文所有代码托管在这儿,如果觉得不错的,可以给个star

    展开全文
  • react-transition-group转场动画: (如果无法播放可点击另存为下载查看) 二、安装 这个演示界面是通过路由实现的,谈到这个我们就不得不提到成熟的react动画库:react-transition-group 首先我们通过npm进行安装...

    一、效果演示

    react-transition-group转场动画:

    (如果无法播放可点击下载查看

    二、安装

    这个演示界面是通过路由实现的,谈到这个我们就不得不提到成熟的react动画库:react-transition-group

    首先我们通过npm进行安装(这里假定你已经学会了使用react-router-dom,react-router,react-router-config)如果你还没有学习,那我建议你稍微进行学习后再来了解路由动画。

    安装命令:

    npm install react-transition-group --save
    

    三、完整源码

    不想看实现过程的请直接看源码实现并进行copy:

    index.js:

    import React from "react";
    import { CSSTransition, TransitionGroup } from "react-transition-group";
    import { Switch, Route, withRouter } from "react-router-dom";
    import "./index.css";
    
    /**
     *
     * @param {way} props
     * @description 用于页面路由跳转 通过way指定跳转方式,指定way=refade
     * 则反向
     *
     */
    const ANIMATION_MAP = {
      PUSH: "fade",
      POP: "refade",
    };
    function AnimationGo(props) {
      const { children } = props;
      // console.log(props.history.action);
      // 根据动作自行判断前进和后退
      /*使用React.cloneElement API对props中的classNames这一props进行修改 */
      return (
        <Route
          render={({ location }) => (
            <TransitionGroup
                
              childFactory={(child) =>
                React.cloneElement(child, {
                  classNames: ANIMATION_MAP[props.history.action],
                })
              }
            >
              <CSSTransition timeout={500} key={location.pathname}>
                <Switch location={location}>{children}</Switch>
              </CSSTransition>
            </TransitionGroup>
          )}
        ></Route>
      );
    }
    
    export default withRouter(AnimationGo);
    
    

    index.css

    /* 入场动画开始 */
    .fade-enter,.fade-appear {
        transform: translateX(100%);
    }
    
    /*入场动画过程*/
    .fade-enter-active,.fade-appear {
        transform: translateX(0);
        transition: transform 0.5s ease;
    }
    
    /*入场动画结束*/
    /* .fade-enter-done {
        transform: translateX(0);
    } */
    
    /*离场动画开始*/
    .fade-exit {
        transform: translateX(0);
    }
    
    /*离场动画过程*/
    .fade-exit-active {
        transform: translateX(-100%);
        transition: transform 0.5s ease;
    }
    
    /*离场动画结束*/
    .fade-exit-done {
        transform: translateX(-100%);
    }
    
    /*页面第一次加载时的开始状态*/
    /* .fade-appear {
        transform: translateX(100%);
    } */
    
    /*页面第一次加载时的动画过程*/
    /* .fade-appear-active {
        transform: translateX(0%);
        transition: transform 0.5s ease-in;
    } */
    
    
    
    
    /* 反向back */
    /*入场动画开始*/
    .refade-enter,.refade-appear {
        transform: translateX(-100%);
    }
    
    /*入场动画过程*/
    .refade-enter-active,.refade-appear-active {
        transform: translateX(0%);
        transition: transform 0.5s ease;
    }
    
    /*入场动画结束*/
    .refade-enter-done {
        transform: translateX(0%);
    }
    
    /*离场动画开始*/
    .refade-exit {
        transform: translateX(0%);
    }
    
    /*离场动画过程*/
    .refade-exit-active {
        transform: translateX(100%);
        transition: transform 0.5s ease;
    }
    
    /*离场动画结束*/
    .refade-exit-done {
        transform: translateX(100%);
    }
    
    /*页面第一次加载时的开始状态*/
    /* .refade-appear {
        transform: translateX(0);
    } */
    
    /*页面第一次加载时的动画过程*/
    /* .refade-appear-active {
        transform: translateX(100%);
        transition: transform 0.5s ease-in;
    } */
    

    挂载组件:

    function App() {
      return (
        <div className="App">
          <Router>
            <AnimationGo>{renderRoutes(routes)}</AnimationGo>
          </Router>
        </div>
      );
    }
    

    四、组件编写分析

    创建组件编写文件夹,在这里同样不加赘述

    首先导入我们所需要的一切控件,在这里,我们将通过函数式组件来构建封装这个组件

    import React from "react";
    import { CSSTransition, TransitionGroup } from "react-transition-group";
    import { Switch, Route, withRouter } from "react-router-dom";
    import "./index.css";
    

    导入的React不必多说,这是编写JSX必须的操作。

    关于react-transition-group,它的用法看上去很类似Vue内置的Transition组件,实际上它就是以vue的transition组件为灵感进行编写的。

    A transition component inspired by the vue transition modes.

    在react-transition-group中,其提供了如下四个组件和一个config对象:

    由于本文重点在于路由跳转动画的实现,所以它的各个详细作用,请自行查看官网文档

    我们在这里需要用到的是CSSTransiton以及TransitionGroup这两个组件,我们先来了解一下这两个组件:

    • CSSTransition用于通过不同CSS的指定形式来展现动画,它有**-enter**(入场动画初始状态,第一帧),-enter-active(入场动画进行时),-enter-done(入场完成后的样式,一般就是-enter-active所指定的末状态,可以不指定),-exit(离场动画初始状态,第一帧),-exit-active(离场状态进行时),-exit-done(与enter-done类似,同样也几乎没有太大意义)这几个关键的CSS类别。

      而CSSTransion有以下几个关键的属性:in,timeout,classNames(注意是classNames,不是className),in属性就是动画开关,classNames即为前文所提到CSS属性名称的前缀部分,timeout即为动画维持时间。

    • TransitionGroup组件,如同它的字面意义,它用于管理一组的过渡组件(比如上文的CSSTransion组件,以及用于其他平台的Transition组件),也就是说,它的子组件,一般是包裹着CSSTransion/Transion组件的组件,它的子组件CSSTransion/Transion上必须指定key属性,利用React根据key值进行diff算法的特性,当发生状态改变的时候,它会暂时保留原本需要移除或变化的子组件,并执行CSSTransion/Transion指定的动画。

    ​ 简单来说,CSSTransion组件用于进行单个组件的动画过程,而通过TransitionGroup可以对多个由 CSSTransion构成的组件进行管理,而在路由切换这一过程中,本质上就是两个view级别(视图级别)组件的切换过程,这一过程中,在必定存在一个如下图所示的过程:

    ​ 也就是说,A与B在进行动画切换的时候必定同时存在,这时候就需要使用到TransitionGroup了。

    展开全文
  • react 路由动画 react-router Switch 组件 react 动画插件 1.插件依赖 使用的插件是react-transition-group。先简单介绍一下动画插件的使用方式。 CSSTransition这个组件有两个比较主要的属性:key和in。 in:...
  • React 路由切换动画

    2021-02-02 21:51:58
    yarn add “react-transition-group”: “^4.4.1”, https://reactcommunity.org/react-transition-group/with-react-router 效果 app.tsx import React, { useCallback } from "react"; import { Redirect, Route...

    环境 create-react-app
    yarn add “react-transition-group”: “^4.4.1”,
    “react”: “^17.0.1”
    “react-router-dom”: “^5.2.0”,

    react-transition-group

    react-router 文档提供的示例

    效果
    屏幕录制2021-02-02 下午10.gif
    动画执行

    import { CSSTransition, TransitionGroup } from "react-transition-group";
    // jsx
    <TransitionGroup>
      <CSSTransition key={location.pathname} classNames="fade" timeout={300}>
        <Switch>
        	<Route xxxx />
    	</Switch>
      </CSSTransition>
    </TransitionGroup>
    

    小bug 当前路径跳转自己
    当前路由跳转自己,一直执行动画组件刷新,正常跳转路径是当前路径是不需要变动的,默认的NavLink跳转自己也是没有变化de
    需要注意的就是<CSSTransition key={location.pathname} ...key属性
    这个key属性,react-router-dom给的示例用的是location.key,我直接复制就出现了这个问题
    key的意思当然就是辨识唯一,如果key不同,动画执行,key相同,不执行动画
    location.key会随机产生,即便跳转的是当前路由
    当执行 replace(“dashboard”);时
    在这里插入图片描述
    可以看到虽然就是当前路由页面也没有变化不过location对象发生变化了,变化的就是key属性
    每次的都不一样,所以用location.key当key会导致这样一个画面
    屏幕录制2021-02-06-下午3.11.01.gif
    一直跳转当前路由带来的是组件的不断创建销毁,呸
    解决: 控制key不变就可以了,简单处理就是使用llocation.pathname`上面问题就可以解决,
    复杂的可以用location.hash 和search配合尝试,还没遇到

    示例:
    路由父组件

    要执行动画组件最外层必须是absolute定位最好是放一个div,父级relative固定下

    import { Layout } from "antd";
    const Content = styled(Layout.Content)`
      position: relative;
      margin: 10px;
      padding: 0;
      display: flex;
    `;
    // jsx
    <StyledContent>
     <TransitionRoute routes={routes} />
    </StyledContent>
    

    动画组件
    TransitionRoute.tsx

    import React from "react";
    import { CSSTransition, TransitionGroup } from "react-transition-group";
    import { Route, Switch, useLocation } from "react-router-dom";
    import { IRoute } from "../type";
    import "./TransitionStyle.css";
    
    interface TransitionRouteProps {
      routes: Array<IRoute>;
    }
    
    const renderRoute = ({ path, Component }: IRoute) => (
      <Route key={path} path={path} component={Component}></Route>
    );
    
    const TransitionRoute: React.FC<TransitionRouteProps> = ({ routes }): any => {
      const location = useLocation();
      
      return (
        <TransitionGroup>
          <CSSTransition key={location.pathname} classNames="fade" timeout={300}>
    		 <Switch location={location}>{routes.map(renderRoute)}</Switch>
          </CSSTransition>
        </TransitionGroup>
      );
    };
    
    export default TransitionRoute;
    

    css文件

    .page-enter {
      opacity: 0;
      transform: scale(1.1);
    }
    
    .page-enter-active {
      opacity: 1;
      transform: scale(1);
      transition: opacity 300ms, transform 300ms;
    }
    
    .page-exit {
      opacity: 1;
      transform: scale(1);
    }
    
    .page-exit-active {
      opacity: 0;
      transform: scale(0.9);
      transition: opacity 300ms, transform 300ms;
    }
    /* .fade-enter {
      opacity: 0;
      z-index: 1;
    }
    
    .fade-enter.fade-enter-active {
      opacity: 1;
      transition: opacity 250ms ease-in;
    } */
    .fade-enter {
      opacity: 0;
      z-index: 1;
      left: 100% !important;
    }
    
    .fade-enter.fade-enter-active {
      opacity: 1;
      left: 0 !important;
      transition: all 300ms ease-in;
    }
    
    .fade-exit {
      opacity: 1;
    }
    
    .fade-exit-active {
      opacity: 0;
      transition: opacity 300ms ease-in;
      /* transition: opacity 300ms, transform 300ms; */
    }
    
    

    需要注意路由组件最外层absolute定位,也不绝对

    展开全文
  • 关于react-native的转场动画这里要依赖于路由库"react-navigation":“3.6.1”,可以实现包括向上转场、向下转场、向左转场、向右转场、缩放、alpha值变化、旋转等多种动画。 二、实现方式 以向左转场为例,...

    一、前言

    关于react-native的转场动画这里要依赖于路由库"react-navigation":“3.6.1”,可以实现包括向上转场、向下转场、向左转场、向右转场、缩放、alpha值变化、旋转等多种动画。

    二、实现方式

    以向左转场为例,我们需要在项目路由下 -> createStackNavigator -> transitionConfig 配置参数如下

    transitionConfig: (sceneProps) => ({
                            transitionSpec: {
                                duration: 3000,
                                // easing: Easing.out(Easing.poly(1)),
                                easing: Easing.bounce,
                                timing: Animated.timing,
                            },
                            screenInterpolator: sceneProps => {
                                const {layout, position, scene} = sceneProps;
                                const {index} = scene;
                                console.log('zhanglei-index:' + index);
                                const height = layout.initHeight;
                                //沿X轴平移
                                const translateX = position.interpolate({
                                    inputRange: [index - 1, index, index + 1],
                                    outputRange: [height, 0, 0],
                                });
                                //沿Y轴平移
                                const translateY = position.interpolate({
                                    inputRange: [index - 1, index, index + 1],
                                    outputRange: [height, 0, 0],
                                });
                                //透明度
                                const opacity = position.interpolate({
                                    inputRange: [0, 0.5, 0.9, 1],
                                    outputRange: [1, 0.25, 0.7, 1],
                                    // inputRange: [index - 1, index - 0.99, index],
                                    // outputRange: [0, 1, 1],
                                });
                                const rotateX = position.interpolate({
                                    inputRange: [0, 0.5, 1],
                                    outputRange: ['0deg', '90deg', '0deg']
                                });
                                const scaleX = position.interpolate({
                                    inputRange: [0, 0.5],
                                    outputRange: [0.8, 1.2],
                                });
                                return {
                                    // opacity,
                                    transform: [
                                        {translateX},
                                        // {translateY},
                                        // {rotateY: rotateX},
                                        // {scale: scaleX},
                                    ]
                                };
                            },
                        }),
    

    实现效果
    在这里插入图片描述
    其他的方式可以通过代码中几种动画的组合来实现,这里由于时间关系就只做个简记,以后再补充。另外我们也可以通过原生路由处理,将页面的转场动画回归到原生开发。

    三、transform样式的使用详解

    可以很明显的看到,这里的动画是主要是由alpha值与transform样式控制的。transform主要可以用于实现平移、缩放、旋转、倾斜等图形变换。

    3.1、平移

    translateX:沿 x 轴方向平移
    translateY:沿 y 轴方向平移

    3.2、缩放

    scaleX:沿 x 轴方向放大
    scaleY:沿 y 轴方向放大
    scale:沿 x、y 轴方向都放大

    3.3、旋转

    rotateX:沿 x 轴旋转
    rotateY:沿 y 轴旋转
    rotateZ:沿 z 轴旋转
    rotate:不指定轴旋转

    3.4、倾斜(或者叫做斜切)

    skewX:沿 x 轴方向倾斜
    skewY:沿 y 轴方向倾斜

    3.5、react-native坐标轴方向

    xyz轴的方向为(手机屏幕面向上,平方在手机上):
    X轴正方向:手机右侧为正,向左为负;
    Y轴正方向:手机下方为正,上方为负;
    Z轴正方向:从手机背面向屏幕指向为负,反之从屏幕向背面指向为正;
    控制旋转中心:https://www.jianshu.com/p/c67559b8f691

    四、内置动画

    另外,react-native内置了几种简单的转场动画,我们可以简单的处理成

    transitionConfig: StackViewStyleInterpolator.forVertical,
    

    其枚举类型有

    import StackViewStyleInterpolator from "react-navigation-stack/dist/views/StackView/StackViewStyleInterpolator";
    export default {
      forHorizontal,
      forVertical,
      forFadeFromBottomAndroid,
      forFadeToBottomAndroid,
      forFade,
      forNoAnimation
    };
    
    展开全文
  • 一、是什么在日常开发中,页面切换时的转场动画是比较基础的一个场景当一个组件在显示与消失过程中存在过渡动画,可以很好的增加用户的体验在react中实现过渡动画效果会有很多种选择,如react...
  • React导航转换 安装 npm install react-navigation-transitions --save 指示 这些功能旨在用作带有的transitionConfig 。 到目前为止,它包括以下过渡: fromLeft fromTop fromRight fromBottom fadeIn ...
  • 使用过Vue2的同学们应该都知道这个内置组件,它可以帮我们添加过渡动画,之前一直用它来给Vue-Router路由的跳转添加转场动画,使用起来非常便捷。那在React中应该如何给路由切换添加过渡动画呢? react-transition-...
  • 基于实现路由转场动画效果 基于实现自动转换px为rem 基于实现PWA(渐进式网络应用程序) 启动 $ yarn $ yarn start $ open http://localhost:7001 $ yarn prod 配置 路由转场动画 | 配置config/config.ssr.js //'''...
  • 原文地址:Animated Transition in React Native! 原文作者:Jiří Otáhal 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m… 译者:talisk 校对者:foxxnuaa 这篇文章有近 15k 的浏览量。对某些...
  • 我们使用 react-transition-group 动画库来实现路由转场动画 核心思路 利用 umi 提供的 layouts 实现全局布局,在路由外面套的一层路由。 利用 react-transition-group 动画库提供的钩子函数,监听到页面退出与...
  • react springOne thing that is pivotal to creating great interactive web applications is animations. Animations add life to your applications and improve the overall user experience. 动画对于创建出色...
  • react-router-transition - 构建用于react-router转场效果,基于react-motion实现
  • react中路由动画的实现需要借助于react匹配的插件react-transition-group。 react-transition-group 基本知识: 在 react 项目中可使用官网提供的动画过渡库 react-transition-group 来实现切换页面(路由切 换)...
  • react 过渡动画

    2021-08-13 20:42:52
    文章目录...两个组件之间切换的炫酷动画 TransitionGroup 列表使用 <TransitionGroup> { list.length > 0 && list.map(item => { return <CSSTransition
  • (一) 前言 版本环境 ...react-native&amp;amp;amp;quot;: &amp;amp;amp;quot;0.57.1&amp;amp;amp;quot;, &amp;amp;amp;quot;react&amp;amp;amp;quot;: &amp;amp;amp;quot;16.5.0
  • react-router 路由切换动画

    千次阅读 2018-12-20 21:22:14
    路由切换动画 因为项目的需求,需要在路由切换的时候,加入一些比较 zb 的视觉效果,所以研究了一下。把这些学习的过程记录下来,以便...react 路由动画 react-router Switch 组件 react 动画插件 1.插件依赖 使...
  • 转载原文:https://www.jianshu.com/p/82552ce3803a 官方文档:https://github.com/chenglou/react-motion 实现一个简单的进出场动画,效果如下: 代码如下: import React, { Component } from 'react' import { ...
  • React 中常见的动画实现方式

    千次阅读 2019-08-06 15:51:35
    自于:https://segmentfault.com/a/1190000012783439 现在,用户对于前端页面的要求已经不能满足于实现功能,更要有颜值,有趣味。除了整体 UI 的美观,在合适的地方添加合适的动画效果往往比静态页面更具有表现力...
  • 因为项目的需求,需要在路由切换的时候,加入一些比较 zb 的视觉效果,所以研究了一下。把这些学习的过程记录下来,以便...使用的插件是react-transition-group。先简单介绍一下动画插件的使用方式。 CSSTransition...
  • GreenSock 是最具影响力的动画平台,同时,它给 React 提供了很多用于创建动画的库或组件。 接下来,进入主题 ????。 CSS 动画 React-transition-group - 它是一个附加组件,用于实现基本的 CSS 动画和过渡动画。...
  • 官方提供了 react-transition-group 库来实现过渡动画,与vue官方提供的 transition 很类似,利用它实现过渡动画。 一、安装 npm : npm install react-transition-group --save yarn : yarn add react-transition-...
  • 作者简介掺水的酱油,携程软件技术专家,关注大前端及移动端相关技术。移动端硬件性能越来越好的今天,页面的交互也越来越丰富,Web 体验在不断向原生应用靠拢,加入了越来越多的手势与动画。除了...
  • 在0.44版本以后就不推荐使用了,官方推荐的是react-navigation,当然还是可以在废弃的库中找到:import { Navigator } from 'react-native-deprecated-custom-components'首先Navigator动画是由Js线程(单线程特点)...
  • react-native 修改Android跳转动画 最近项目发现android跳转动画是上下跳转的,不是很习惯这种跳转方式,准备修改为左右跳转,查了各种方案很神奇都没有生效。马上要放弃的时候无意间看见WARN中的一条警告信息 '...
  • React Native开发之动画(Animations)

    万次阅读 2016-06-28 14:21:52
    React Native开发之IDE(Atom+Nuclide) React Native开发之FlexBox代码+图解 React Native的Navigator详解 另外,我在Github上建立了一个仓库来搜集优秀的React Native库和优秀的博客等ReactNativeMaterials资料 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,687
精华内容 2,674
关键字:

react转场动画