react动画

安装 react-transition-group

js 复制代码
npm i react-transition-group -D

CSSTransition: 原理

  • <CSSTransition> 会修改 <h1>的className
  • className 变化分3个阶段
  • 进入
    • 阶段1: enter, 第一次渲染
    • 阶段2: enter-active, 第二次渲染(回流)
    • 阶段3: enter-done, 动画结束进入第三阶段
  • 退出
    • 阶段1:exit, 第一次渲染
    • 阶段2:exit-active, 第二次渲染(回流)
    • 阶段3:exit-done, 动画结束进入第三阶段
jsx 复制代码
import { useState } from "react";
import { CSSTransition } from "react-transition-group";

function App() {
  const [show, setShow] = useState(true);

  return (
    <div>
      <CSSTransition in={show} timeout={2000}>
        <h1>hellow</h1>
      </CSSTransition>

      <button onClick={() => setShow(true)}>显示</button>
      <button onClick={() => setShow(false)}>隐藏</button>
    </div>
  );
}

export default App;

点击显示按钮, h1的class的变化

jsx 复制代码
// 阶段1
<h1 class="enter">hellow</h1>
// 阶段2: 重绘重排
<h1 class="enter enter-active">hellow</h1>
// 阶段3:动画时长是2秒, 说以两秒钟后变成"enter-done"
<h1 class="enter-done">hellow</h1>

点击隐藏按钮, h1的class的变化

jsx 复制代码
// 阶段1
<h1 class="exit">hellow</h1>
// 阶段2: 重绘重排, 如果不回流就看不到过渡动画
<h1 class="exit enter-active">hellow</h1>
// 阶段3: 动画时长是2秒, 说以两秒钟后变成"exit-done"
<h1 class="exit-done">hellow</h1>

淡入淡出

版本1

app.jsx

jsx 复制代码
import { useState } from "react";
import { CSSTransition } from "react-transition-group";
import "./App.css";

function App() {
  const [show, setShow] = useState(true);

  return (
    <div>
      {/* timeout时长由动画时长决定 */}
      <CSSTransition in={show} timeout={2000}>
        <h1>hellow</h1>
      </CSSTransition>

      <button onClick={() => setShow(true)}>显示</button>
      <button onClick={() => setShow(false)}>隐藏</button>
    </div>
  );
}

export default App;

app.css

css 复制代码
/* 淡入动画 */

/* 阶段1 */
.enter {
  opacity: 0;
}
/* 阶段2 */
.enter-active {
  opacity: 1;
  transition: 2s;
}

/* 淡出动画 */

/* 阶段1 */
.exit {
  opacity: 1;
}
/* 阶段2 */
.exit-active {
  opacity: 0;
  transition: 2s;
}
/* 阶段3 */
.exit-done {
  display: none;
}

版本2: 有加载动画

版本1:

  • 组件加载到页面时: 没有动画
  • 点击显示按钮时: 淡入动画
  • 点击隐藏按钮时: 淡出动画

版本2

  • 组件加载到页面时: 淡入动画
  • 点击显示按钮时: 淡入动画
  • 点击隐藏按钮时: 淡出动画

实现方式:

  • 添加属性 appear: <CSSTransition appear />

  • appear也分三个阶段

    • 阶段1:appear, 第一次渲染
    • 阶段2:appear-active, 第二次渲染(回流)
    • 阶段3:appear-done, 动画结束进入第三阶段
  • 下面是className的变化

    • 页面完整加载:
      • 阶段1: className='appear'
      • 阶段2: className='appear appear-active'
      • 阶段3: className='appear-done'
    • 点击隐藏按钮:
      • 阶段1: className='exit'
      • 阶段2: className='exit exit-active'
      • 阶段3: className='exit-done'
    • 点击显示按钮:
      • 阶段1: className='enter'
      • 阶段2: className='enter enter-active'
      • 阶段3: className='enter-done'

app.jsx

jsx 复制代码
import { useState } from "react";
import { CSSTransition } from "react-transition-group";
import "./App.css";

function App() {
  const [show, setShow] = useState(true);

  return (
    <div>
      // appear属性是为了实现加载动画
      <CSSTransition appear in={show} timeout={2000}>
        <h1>hellow</h1>
      </CSSTransition>

      <button onClick={() => setShow(true)}>显示</button>
      <button onClick={() => setShow(false)}>隐藏</button>
    </div>
  );
}

export default App;

app.css

css 复制代码
/* 进入 */
/* 进入: 阶段1 */
.appear,
.enter {
  opacity: 0;
}
/* 进入: 阶段2 */
.appear-active,
.enter-active {
  opacity: 1;
  transition: 2s;
}

/* 退出 */
/* 退出: 阶段1 */
.exit {
  opacity: 1;
}
/* 退出: 阶段2 */
.exit-active {
  opacity: 0;
  transition: 2s;
}
/* 退出: 阶段3 */
.exit-done {
  display: none;
}

切换动画

  • 第一次点击按钮: jack淡出, tom淡入
  • 第二次点击按钮: tom淡出, jack淡入

版本1

app.jsx

jsx 复制代码
import { useState } from "react";
import { CSSTransition } from "react-transition-group";
import "./App.css";

function App() {
  const [show, setShow] = useState(true);

  return (
    <div>
      <CSSTransition in={show} timeout={2000}>
        <h1>jack</h1>
      </CSSTransition>

      {/* 如果没有属性 mountOnEnter: 页面加载完成后, jack 和 tom 都会显示出来 */}
      {/* 但是我们希望看到的是: 页面加载完成时, jack显示, tom隐藏 */}
      {/* in=false时, 有属性mountOnEnter:  页面加载完成时, tom不显示*/}
      {/* in=false时, 无属性mountOnEnter:  页面加载完成时, tom会显示*/}
      <CSSTransition mountOnEnter in={!show} timeout={2000}>
        <h1>tom</h1>
      </CSSTransition>

      <button onClick={() => setShow(!show)}>trigger</button>
    </div>
  );
}

export default App;

app.css

css 复制代码
h1 {
  position: absolute;
  left: 50%;
  right: 50%;
}
/* 进入 */
/* 进入: 阶段1 */
.enter {
  opacity: 0;
  transform: translateX(100px);
}
/* 进入: 阶段2 */
.enter-active {
  opacity: 1;
  transform: translateX(0);
  transition: 2s;
}

/* 退出 */
/* 退出: 阶段1 */
.exit {
  opacity: 1;
  transform: translateX(0);
}
/* 退出: 阶段2 */
.exit-active {
  opacity: 0;
  transform: translateX(-100px);
  transition: 2s;
}
/* 退出: 阶段3 */
.exit-done {
  display: none;
}

版本2: 用animate.css实现

  • h1 className 的变化

    • 淡入
      • 阶段1: className="enter"
      • 阶段2: className="enter fadeInRight"
      • 阶段3: className='enter-done'
    • 淡出
      • 阶段1: className="exit"
      • 阶段2: className="exit fadeOutLeft"
      • 阶段3: className='exit-done'
  • 解释: className="animated fast"

    • 使用animate.css都得添加 animated
    • animated: animate.css的基本配置
    • fast: 表示动画时长, 800ms

app.jsx

jsx 复制代码
import { useState } from "react";
import { CSSTransition } from "react-transition-group";
import "./App.css";
import "animate.css";

function App() {
  const [show, setShow] = useState(true);

  const clas = {
    enterActive: "fadeInRight", // 来自animate.css
    exitActive: "fadeOutLeft", // 来自animate.css
    exitDone: "exit-done", // App.css
  };

  return (
    <div>
      <CSSTransition classNames={clas} in={show} timeout={800}>
        <h1 className="animated fast">jack</h1>
      </CSSTransition>

      <CSSTransition classNames={clas} mountOnEnter in={!show} timeout={800}>
        <h1 className="animated fast">tom</h1>
      </CSSTransition>

      <button onClick={() => setShow(!show)}>trigger</button>
    </div>
  );
}

export default App;

app.css

css 复制代码
h1 {
  position: absolute;
  left: 50%;
  top: 50%;
}

.exit-done {
  display: none;
}

多个动画

实现效果

  • 点击隐藏按钮: jack宽度变为0, tom高度变为0
  • 点击显示按钮: jack变宽, tom变高

写法1

app.jsx

jsx 复制代码
import { useState } from "react";
import { CSSTransition } from "react-transition-group";
import "./App.css";

function App() {
  const [show, setShow] = useState(true);

  return (
    <div>
      <CSSTransition classNames="w" in={show} timeout={2000}>
        <h1>jack</h1>
      </CSSTransition>

      <CSSTransition classNames="h" in={show} timeout={2000}>
        <h1>tom</h1>
      </CSSTransition>

      <button onClick={() => setShow(true)}>显示</button>
      <button onClick={() => setShow(false)}>隐藏</button>
    </div>
  );
}

export default App;

app.css

css 复制代码
h1 {
  background-color: red;
  overflow: hidden;
  white-space: nowrap;
}
/* 动画1: 宽度变化 */
.w-enter {
  width: 0px;
}

.w-enter-active {
  width: 100%;
  transition: 2s;
}

.w-exit {
  width: 100%;
}

.w-exit-active {
  width: 0px;
  transition: 2s;
}

.w-exit-done {
  display: none;
}

/* 动画2: 高度变化 */
.h-enter {
  height: 0px;
}

.h-enter-active {
  height: 50px;
  transition: 2s;
}

.h-exit {
  height: 50px;
}

.h-exit-active {
  height: 0px;
  transition: 2s;
}

.h-exit-done {
  display: none;
}

写法2

jsx 复制代码
import { useState } from "react";
import { CSSTransition } from "react-transition-group";
import "./App.css";

function App() {
  const [show, setShow] = useState(true);

  // 指定各个阶段的 className
  const w = {
    enter: "w-enter", // 阶段1
    enterActive: "w-enter-active", // 阶段2
    enterDone: "w-enter-done", // 阶段3
    exit: "w-exit", // 阶段1
    exitActive: "w-exit-active",// 阶段2
    exitDone: "w-exit-done",// 阶段3
  };

  const h = {
    enter: "h-enter",// 阶段1
    enterActive: "h-enter-active",// 阶段2
    enterDone: "h-enter-done",// 阶段3
    exit: "h-exit",// 阶段1
    exitActive: "h-exit-active",// 阶段2
    exitDone: "h-exit-done",// 阶段3
  };

  return (
    <div>
      <CSSTransition classNames={w} in={show} timeout={2000}>
        <h1>宽度发生变化</h1>
      </CSSTransition>

      <CSSTransition classNames={h} in={show} timeout={2000}>
        <h1>高度发生变化</h1>
      </CSSTransition>

      <button onClick={() => setShow(true)}>显示</button>
      <button onClick={() => setShow(false)}>隐藏</button>
    </div>
  );
}

export default App;
相关推荐
GHOME2 小时前
原型链的原貌
前端·javascript·面试
bug_kada2 小时前
Flex布局/弹性布局(面试篇)
前端·面试
元元不圆2 小时前
JSP环境部署
前端
槿泽2 小时前
Vue集成Electron目前最新版本
前端·vue.js·electron
luckyCover2 小时前
带你一起攻克js之原型到原型链~
前端·javascript
麦当_2 小时前
SwipeMultiContainer 滑动切换容器算法指南
前端·javascript·算法
星斗大森林2 小时前
Flame游戏开发——噪声合成、域变换与阈值/调色映射的工程化实践(2)
前端
星斗大森林2 小时前
flame游戏开发——地图拖拽与轻点判定(3)
前端
samonyu2 小时前
fnm 简介及使用
前端·node.js