安装 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:
- 退出
- 阶段1:
exit
, 第一次渲染 - 阶段2:
exit-active
, 第二次渲染(回流) - 阶段3:
exit-done
, 动画结束进入第三阶段
- 阶段1:
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
, 动画结束进入第三阶段
- 阶段1:
-
下面是
className
的变化- 页面完整加载:
- 阶段1:
className='appear'
- 阶段2:
className='appear appear-active'
- 阶段3:
className='appear-done'
- 阶段1:
- 点击隐藏按钮:
- 阶段1:
className='exit'
- 阶段2:
className='exit exit-active'
- 阶段3:
className='exit-done'
- 阶段1:
- 点击显示按钮:
- 阶段1:
className='enter'
- 阶段2:
className='enter enter-active'
- 阶段3:
className='enter-done'
- 阶段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>
// 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;