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;
相关推荐
sean9 分钟前
开发一个自己的 claude code
前端·后端·ai编程
用户214118326360213 分钟前
dify案例分享-用 Dify 一键生成教学动画 HTML!AI 助力,3 分钟搞定专业级课件
前端
太过平凡的小蚂蚁2 小时前
Kotlin 协程中常见的异步返回与控制方式(速览)
开发语言·前端·kotlin
咖啡の猫3 小时前
Vue初始化脚手架
前端·javascript·vue.js
晨枫阳3 小时前
uniapp兼容问题处理总结
前端·vue.js·uni-app
liusheng4 小时前
腾讯地图 SDK 接入到 uniapp 的多端解决方案
前端·uni-app
拉不动的猪4 小时前
如何处理管理系统中(Vue PC + uni-app 移动端):业务逻辑复用基本方案
前端·javascript·架构
边洛洛5 小时前
next.js项目部署流程
开发语言·前端·javascript
Zsnoin能5 小时前
浏览器连接 新北洋BTP-P33/P32蓝牙打印机,打印 二维码
前端
非凡ghost5 小时前
Syncovery Premium(文件同步软件)
前端·javascript·后端