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;
相关推荐
IT_陈寒11 分钟前
「Redis性能翻倍的5个核心优化策略:从数据结构选择到持久化配置全解析」
前端·人工智能·后端
weixin_4469388716 分钟前
uniapp vue-i18n如何使用
前端·vue.js·uni-app
知识分享小能手29 分钟前
微信小程序入门学习教程,从入门到精通,WXS语法详解(10)
前端·javascript·学习·微信小程序·小程序·vue·团队开发
excel32 分钟前
Vue 组件与插件的区别详解
前端
JarvanMo2 小时前
Flutter 开发:应用颜色使用 Class 还是 Enum?—— 你应该选择哪一个?
前端
HBR666_2 小时前
AI编辑器(二) ---调用模型的fim功能
前端·ai·编辑器·fim·tiptap
csgo打的菜又爱玩5 小时前
Vue 基础(实战模板与命名指南)
前端·javascript·vue.js
ding_zhikai6 小时前
SD:在一个 Ubuntu 系统安装 stable diffusion Web UI
前端·ubuntu·stable diffusion
gerrgwg7 小时前
Vue-library-start,一个基于Vite的vue组件库开发模板
前端·javascript·vue.js
你的人类朋友8 小时前
【Node】单线程的Node.js为什么可以实现多线程?
前端·后端·node.js