文章目录
简介
在项目中可能会有一些动画效果展示或页面切换效果,使用css动画的方式虽然可以实现,但比较局限,涉及到一些js动画的时候就没法处理了。
react-transition-group是react的第三方模块,借助这个模块可以更加方便的实现更加复杂的动画效果
- 官网地址:
- https://reactcommunity.org/react-transition-group/css-transition
- 该三方包的安装命令如下:
npm i -S react-transition-group
基本使用
步骤:
1. 需要定义好css动画的样式
2. 按照transtion动画组的语法去使用css样式
-
app.css
文件
/* app.css,来自于官网 */
.alert-enter {
opacity: 0;
transform: scale(0.9);
}
.alert-enter-active {
opacity: 1;
transform: translateX(0);
transition: opacity 300ms, transform 300ms;
}
.alert-exit {
opacity: 1;
}
.alert-exit-active {
opacity: 0;
transform: scale(0.9);
transition: opacity 300ms, transform 300ms;
}
.alert-exit-done {
display: none;
}
-
App.jsx
文件
import React, { Component, Fragment } from "react";
import { CSSTransition } from "react-transition-group";
import "./assets/app.css";
class App extends Component {
state = {
// 是否显示
isShow: true,
};
handleToggole = () => {
this.setState(() => {
return {
isShow: !this.state.isShow,
};
});
};
render() {
return (
<Fragment>
<CSSTransition
{/* in:表示控制默认是否显示 */}
in={this.state.isShow}
{/* timeout:动画所持续的时间,单位:毫秒 */}
timeout={ 300 }
{/* classNames:class样式类名 */}
classNames={{
enter: "alert-enter",
enterActive: "alert-enter-active",
exit: "alert-exit",
exitActive: "alert-exit-active",
}}
{/* unmountOnExit:在元素退出的时候删除对应的DOM */}
unmountOnExit
>
<div>玩转React Transition</div>
</CSSTransition>
<button onClick={this.handleToggole}>
触发动画
</button>
</Fragment>
);
}
}
export default App;
在上述demo中,我们的动画样式来自于官网的案例,但是以后写项目的时候,样式肯定不能用刚才的,那此时就需要我们自己写样式了,这是一个好时而且费力的工作。为了便于高效开发,对于常见的动画效果,前辈们已经给我们造好*了,我们只需要拿过来直接使用即可。
- 常用动画库:animate.css
- 安装方式一:
$ npm install animate.css --save
或
$ yarn add animate.css
- 安装方式二:
- 在
animate.css
官网找到CDN
外链地址,打开后将animate.min.css
文件保存到本地:
<head>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
/>
</head>
- 随后将
animate.min.css
文件放到项目中,假定放置到./src/assets/css/animate.min.css
,则随后在需要使用animate
动画的组件中按照以下方式进行导入:
import "./assets/css/animate.min.css";
- 导入好以后,根据
animate
官网的演示效果复制所需要的动画样式类名(切勿使用浏览器自带的翻译功能翻译页面,否则会导致样式演示效果无法预览),替换react-transition-group
配置部分的对应classNames
样式值名即可,例如:
render() {
return (
<Fragment>
<CSSTransition
in={this.state.isShow}
timeout={1000}
classNames={{
enter: "animate__animated",
enterActive: "animate__fadeInDown",
exit: "animate__animated",
exitActive: "animate__fadeOutDown",
}}
unmountOnExit
>
<div>玩转React Transition</div>
</CSSTransition>
<button onClick={this.handleToggole}>触发动画</button>
</Fragment>
);
}
列表过渡动画
此处单独靠
CSSTransition
是不能实现列表的动画的,因为CSSTransition
只针对单个元素进行动画效果
- 核心代码
<TransitionGroup>
<CSSTransition>
<li>aaaa</li>
</CSSTransition>
</TransitionGroup>
- 案例目标
import React, { Component } from "react";
// 导入动画组件包中的内容
import { TransitionGroup, CSSTransition } from "react-transition-group";
import "./assets/css/animate.min.css";
// 实现步骤:
// 1. 按照两步去走(任务分解)
// - 先实现没有动画的效果
// - 实现上一步后再去考虑加上动画效果
// 2. 以当前案例为例,有有少个h5标签,最终其实就有多少个CSSTransition组件
class App extends Component {
state = {
username: ["张三"],
};
render() {
return (
<div>
<div>
<button onClick={this.handler.bind(this)}>添加</button>
<hr />
{/* 展示列表的数据 */}
<TransitionGroup>
{this.state.username.map((item, index) => {
return (
<CSSTransition
timeout={1000}
classNames={{
enter: "animate__animated",
enterActive:
"animate__animated animate__fadeInUp"
}}
key={index}
>
<h5 key={index}>{item}</h5>
</CSSTransition>
);
})}
</TransitionGroup>
</div>
</div>
);
}
// 点击事件处理函数
handler() {
this.setState((state) => {
// 产生新的数据(不重复的名字)
let tmp = "李四" + Math.random();
return { username: [...state.username, tmp] };
});
}
}
路由过渡动画
路由过渡动画,即路由切换时为其添加动画效果。其实现思路与列表的过渡动画类似。
- 案例效果
import React, { Component } from "react";
// 思想步骤:先去实现不带动画效果的,再实现动画效果
// 这里有一个坑:
import { Route, Link, Switch, withRouter } from "react-router-dom";
import About from "./Components/About";
import News from "./Components/News";
// 导入动画组件
import { TransitionGroup,CSSTransition } from "react-transition-group";
import "./assets/css/animate.min.css"
class App extends Component {
render() {
return (
<div>
<ul>
<li>
<Link to="/about">关于</Link>
</li>
<li>
<Link to="/news">新闻</Link>
</li>
</ul>
<TransitionGroup>
{/* 因为switch只会匹配一个路由,因此可以直接使用CSSTransition包裹Switch */}
<CSSTransition
timeout={1000}
classNames={{
enter: "animate__animated",
enterActive:
"animate__animated animate__fadeInDown",
exit: "animate__animated",
exitActive: "animate__animated animate__fadeOutUp",
}}
// 加key让CSSTransition知道自己的内容发生了变化,要求key值不重复
// 此处的key并不是为了提供效率,而是为了让框架强制重新渲染CSSTransition
key={this.props.location.pathname}
>
<Switch>
<Route path="/about" component={About}></Route>
<Route path="/news" component={News}></Route>
</Switch>
</CSSTransition>
</TransitionGroup>
</div>
);
}
}
export default withRouter(App);