过渡动画
在开发中,我们想要给一个组件的显示和消失添加某种过渡动画,可以很好的增加用户体验。当然,我们可以通过原生的CSS来实现这些过渡动画,但是React社区为我们提供了react-transition-group用来完成过渡动画。React曾为开发者提供过动画插件 react-addons-css-transition-group,后由社区维护,形成了现在的 react-transition-group。 这个库可以帮助我们方便的实现组件的 入场 和 离场 动画,使用时需要进行额外的安装。react-transition-group本身非常小,不会为我们应用程序增加过多的负担。
安装指令
npm install react-transition-group --save
react-transition-group 四组件
Transition
- 该组件是一个和平台无关(RN也可以)的组件(不一定要结合CSS)
- 在前端开发中,我们一般是结合CSS来完成样式,所以比较常用的是CSSTransition
CSSTransition
- 在前端开发中,通常使用CSSTransition来完成过渡动画效果
SwitchTransition
- 两个组件显示和隐藏切换时,使用该组件
TransitionGroup
- 将多个动画组件包裹在其中,一般用于列表中元素的动画
演示CSSTransition
我们结合antd的card组件。
import React, { PureComponent } from 'react'
import { CSSTransition } from 'react-transition-group' //引入CSSTransition
import { EditOutlined, EllipsisOutlined, SettingOutlined } from '@ant-design/icons';
import { Avatar, Card } from 'antd';
const { Meta } = Card;
export default class CSSTransitionDemo extends PureComponent {
constructor(props){
super(props)
this.state = {
isShow : true
}
}
render() {
const {isShow} = this.state
return (
<div>
<button onClick={e => {this.setState({isShow :!isShow})} }>显示/隐藏</button>
{/* 是names不是name */}
{/* unmountOnExit true 退出删掉组件 刷新不会有动画 */}
{/* appear第一次出现 */}
<CSSTransition in = {isShow}
classNames = "card"
timeout={300}
unmountOnExit = {true}
appear
>
<Card
style={{
width: 300,
}}
cover={
<img
alt="example"
src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png"
/>
}
actions={[
<SettingOutlined key="setting" />,
<EditOutlined key="edit" />,
<EllipsisOutlined key="ellipsis" />,
]}
>
<Meta
avatar={<Avatar src="https://joeschmoe.io/api/v1/random" />}
title="Card title"
description="This is the description"
/>
</Card>
</CSSTransition>
</div>
)
}
}
CSS
.card-enter, .card-appear{
opacity: 0;
transform: scale(.6);
}
.card-enter-active, .card-appear-active{
opacity: 1;
transform: scale(1);
transition: all 300ms;
}
.card-enter-done, .card-appear-done{
}
.card-exit{
opacity: 1;
transform: scale(1)
}
.card-exit-active{
opacity: 0;
transform: scale(.6);
transition: all 300ms;
}
.card-exit-done{
opacity: 0;
}
添加了names以后:
生命周期的钩子:
import React, { PureComponent } from 'react'
import { CSSTransition } from 'react-transition-group' //引入CSSTransition
import { EditOutlined, EllipsisOutlined, SettingOutlined } from '@ant-design/icons';
import { Avatar, Card } from 'antd';
const { Meta } = Card;
export default class CSSTransitionDemo extends PureComponent {
constructor(props){
super(props)
this.state = {
isShow : true
}
}
render() {
const {isShow} = this.state
return (
<div>
<button onClick={e => {this.setState({isShow :!isShow})} }>显示/隐藏</button>
{/* 是names不是name */}
{/* unmountOnExit true 退出删掉组件 刷新不会有动画 */}
{/* appear第一次出现 */}
<CSSTransition in = {isShow}
classNames = "card"
timeout={300}
unmountOnExit = {true}
appear
onEnter={el => console.log("进入状态")}
onEntering={el => console.log("正在进入")}
onEntered={el => console.log("进入完成")}
onExit={el => console.log("退出状态")}
onExiting={el => console.log("正在退出")}
onExited={el => console.log("退出完成")}
>
<Card
style={{
width: 300,
}}
cover={
<img
alt="example"
src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png"
/>
}
actions={[
<SettingOutlined key="setting" />,
<EditOutlined key="edit" />,
<EllipsisOutlined key="ellipsis" />,
]}
>
<Meta
avatar={<Avatar src="https://joeschmoe.io/api/v1/random" />}
title="Card title"
description="This is the description"
/>
</Card>
</CSSTransition>
</div>
)
}
}
演示SwitchTransition
import React, { PureComponent } from 'react'
import "./SwitchTransition.css"
import {SwitchTransition,CSSTransition} from 'react-transition-group'
export default class SwitchtTransitionDemo extends PureComponent {
constructor(props){
super(props)
this.state = {
isOn:true
}
}
render() {
const {isOn} = this.state;
return (
<div>
<SwitchTransition mode='in-out'>
<CSSTransition
key={isOn? "on" : "false" }
classNames = "btn"
timeout={1000}
>
<button onClick={ e => this.setState({isOn:!isOn})}>{isOn ? "on" : "off"}</button>
</CSSTransition>
</SwitchTransition>
</div>
)
}
}
.btn-enter {
opacity: 0;
transform: translateX(100%);
}
.btn-enter-active{
opacity: 1;
transform: translateX(0);
transition: all 1000ms;
}
.btn-exit{
opacity: 1;
}
.btn-exit-active{
opacity: 0;
transform: translateX(-100%);
transition: all 1000ms;
}
这是控制类添加的时间。
动画是由CSS控制的。
演示TransitionGroup
import React, { PureComponent } from 'react'
import { CSSTransition, TransitionGroup } from 'react-transition-group';
import './TransitionGroup.css';
export default class TransitionGroupDemo extends PureComponent {
constructor(props) {
super(props)
this.state = {
names: ["harry", "kobe", "lilei"]
}
}
render() {
return (
<div>
<TransitionGroup>
{
this.state.names.map((item, index) => {
return (
// 这个key是react优化的那个key,这里最后追加索引是能做优化的
<CSSTransition
key={index}
timeout={500}
classNames="item"
>
<div> {item} </div>
</CSSTransition>
)
})
}
<button onClick={e => this.addName()}>+name</button>
</TransitionGroup>
</div>
)
}
addName() {
this.setState({
names: [...this.state.names, "harry"]
})
}
}
.item-enter {
opacity: 0;
transform: scale(.6);
}
.item-enter-active {
opacity: 1;
transform: scale(1);
transition: opacity 300ms, transform 300ms;
}
.item-enter-done {
color: red;
}
.item-exit {
opacity: 1;
transform: scale(1);
}
.item-exit-active {
opacity: 0;
transform: scale(.6);
transition: opacity 300ms, transform 300ms;
}
.item-exit-done {
opacity: 0;
}