react应用的路由切换动画

展示地址

应用首次加载时候的动画。

首次加载.gif

切换路由时候的动画

切换.gif

做react路由动画比较复杂,最好了解三个前提知识,

  1. react动画组件,react-transition-group 文档

  2. react路由组件,react-router 文档

  3. css动画语法, CSS动画简介 文档

直接上代码

这里我直接用了官方的demo代码,并且稍微改了一下动画样式。附上我写好的github项目地址

//index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { TransitionGroup, CSSTransition } from "react-transition-group";
import './App.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';

ReactDOM.render(
  // 这个动画是页面首次加载的动画,设置appear={true} 这个属性,并且动画时间设置为500ms,和css中的需要一致。
  // 一定要用 TransitionGroup 包着 CSSTransition,动画才有效,
  // 原因是TransitionGroup 负责检测并自动给CSSTransition添加‘in’的prop,
  // 并且TransitionGroup 要一直存在,不能放在动态生成的组件中.
  <TransitionGroup>
    <CSSTransition
      appear={true}
      classNames="appAppear"
      timeout={500}
    >
      <App/>
    </CSSTransition>
  </TransitionGroup>,
  document.getElementById('root')
);
registerServiceWorker();

// app.js

import React from "react";
import { TransitionGroup, CSSTransition } from "react-transition-group";
import { BrowserRouter , Switch, Route, Link, Redirect } from "react-router-dom";
import './App.css'

const AnimationRoute = () => (
  <BrowserRouter>
    <Route
      render={({ location }) => (
        <div style={styles.fill}>
          <Route
            exact
            path="/"
            render={() => <Redirect to="/hsl/10/90/50" />}
          />

          <ul style={styles.nav}>
            <NavLink to="/hsl/10/90/50">Red</NavLink>
            <NavLink to="/hsl/120/100/40">Green</NavLink>
            <NavLink to="/rgb/33/150/243">Blue</NavLink>
            <NavLink to="/rgb/240/98/146">Pink</NavLink>
          </ul>

          <div>{console.log(location)}</div>
          <div style={styles.content}>
            {/*和平时使用动画组件没啥区别,*/}
            {/*在渲染的路由的地方加一个用动画组件包着,并添加css属性即可;*/}
            <TransitionGroup>
              <CSSTransition
                // 需要加一个key属性,让react认识每个组件,并进行正确的加载。
                // 这里我改了官方demo的代码, 原来是设置成location.key, 这样的话每次点击同一个路由链接的时候都会渲染。
                key={location.pathname}
                // classNames 就是设置给css动画的标示,记得'classNames'带's'的。
                classNames="fade"
                // 动画时间设置为800ms,和css中的需要一致。
                timeout={800}
              >
                <Switch location={location}>
                  <Route exact path="/hsl/:h/:s/:l" component={HSL} />
                  <Route exact path="/rgb/:r/:g/:b" component={RGB} />
                  <Route render={() => <div>Not Found</div>} />
                </Switch>
              </CSSTransition>
            </TransitionGroup>
          </div>
        </div>
      )}
    />
  </BrowserRouter>
);

const NavLink = props => (
  <li style={styles.navItem}>
    <Link {...props} style={{ color: "inherit" }} />
  </li>
);

const HSL = ({ match: { params } }) => (
  <div
    style={{
      ...styles.fill,
      ...styles.hsl,
      background: `hsl(${params.h}, ${params.s}%, ${params.l}%)`
    }}
  >
    hsl({params.h}, {params.s}%, {params.l}%)
  </div>
);

const RGB = ({ match: { params } }) => (
  <div
    style={{
      ...styles.fill,
      ...styles.rgb,
      background: `rgb(${params.r}, ${params.g}, ${params.b})`
    }}
  >
    rgb({params.r}, {params.g}, {params.b})
  </div>
);

const styles = {};

styles.fill = {
  position: "absolute",
  left: 0,
  right: 0,
  top: 0,
  bottom: 0
};

styles.content = {
  ...styles.fill,
  top: "40px",
  textAlign: "center"
};

styles.nav = {
  padding: 0,
  margin: 0,
  position: "absolute",
  top: 0,
  height: "40px",
  width: "100%",
  display: "flex"
};

styles.navItem = {
  textAlign: "center",
  flex: 1,
  listStyleType: "none",
  padding: "10px"
};

styles.hsl = {
  ...styles.fill,
  color: "white",
  paddingTop: "20px",
  fontSize: "30px"
};

styles.rgb = {
  ...styles.fill,
  color: "white",
  paddingTop: "20px",
  fontSize: "30px"
};

export default AnimationRoute;


//App.css


/*这里定义整个应用加载时的动画,进场前这里设置了缩放为0,
进场过程中缩放变为1,也就是100%,持续时间为500ms,
时间曲是ease-out,一种先快后慢的变化曲线*/

.appAppear-appear{
  opacity: 0;
  transform: scale(0);
}

.appAppear-appear.appAppear-appear-active{
  opacity: 1;
  transform: scale(1);
  transition: 500ms ease-out;
}

/*设置进场前透明度为0,放缩为0*/

.fade-enter {
  opacity: 0;
  transform: scale(0);
}


/*设置进场过程中 透明度为1,放缩为1,放缩的位置为左上角,持续时间为500ms,时间曲是ease-out */
.fade-enter.fade-enter-active {
  opacity: 1;
  transform: scale(1);
  transform-origin: top left;
  transition: 800ms ease-out;
}

/*设置退场前透明度为1,放缩为1*/
.fade-exit{
  opacity: 1;
  transform: scale(1);
}

/*设置退场过程中 透明度为0,放缩为0,放缩的位置默认是中间,所以不设置也可以,
持续时间为500ms,时间曲是ease-out */
.fade-exit.fade-exit-active{
  opacity:0;
  transform: scale(0);
  transition: 800ms ease-out;
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,591评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,448评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,823评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,204评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,228评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,190评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,078评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,923评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,334评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,550评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,727评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,428评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,022评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,672评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,826评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,734评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,619评论 2 354

推荐阅读更多精彩内容