React-Transition-Group动画过渡

652 阅读3分钟

过渡动画

在开发中,我们想要给一个组件的显示和消失添加某种过渡动画,可以很好的增加用户体验。当然,我们可以通过原生的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

image.png

image.png

我们结合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以后:

image.png image.png

生命周期的钩子: image.png image.png image.png

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

image.png

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;
}

这是控制类添加的时间。 image.png 动画是由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;
}