【React】动画库:react-transition-group

react-transition-group提供了用于定义动画的简单组件,该库并未定义样式本身,而是以有用的方式操作DOM,从而使过渡和动画的实现更加舒适。换言之,react-transition-group提供了一种更简单的动画和过渡方法。

安装

// npm
npm install react-transition-group --save
​
// yarn
yarn add react-transition-group
复制代码

官方提供四个组件,分别为 Transition, CSSTransition,SwitchTransition, TransitonGroup。

Transition

Transition组件允许你使用简单的声明性API描述随时间从一个组件状态到另一个组件状态的转换。最常见的是,它被用于动画组件的挂载和卸载,但也可以用于描述就地转换状态。

注意:Transition是一个平台无关的基础组件。如果你在CSS中使用过渡,你可能会想要使用CSS过渡。它继承了Transition的所有特性,但包含了其他必要的特性,以更好地处理CSS过渡(因此该组件的名称)。

默认情况下Transition组件不会改变它呈现的组件的行为,它只跟踪组件的“进入”和“退出”状态。这取决于你赋予这些状态意义和效果。例如,当组件进入或退出时,我们可以向它添加样式。

在一个过渡中有四种主要状态:

  • entering
  • entered
  • exiting
  • exited

过渡状态通过in属性切换。当为true时,组件开始“Enter”阶段。在此阶段中,组件将从当前转换状态转移到转换期间的“进入”状态,然后在完成转换后再转移到“进入”状态。

import { Transition } from 'react-transition-group';
​
const duration = 300;
​
const defaultStyle = {
  transition: `opacity ${duration}ms ease-in-out`,
  opacity: 0,
}
​
const transitionStyles = {
  entering: { opacity: 1 },
  entered:  { opacity: 1 },
  exiting:  { opacity: 0 },
  exited:  { opacity: 0 },
};
​
const Fade = ({ in: inProp }) => (
  <Transition in={inProp} timeout={duration}>
    {state => (
      <div style={{
        ...defaultStyle,
        ...transitionStyles[state]
      }}>
        I'm a fade Transition!
      </div>
    )}
  </Transition>
);
复制代码
参数 说明 类型 默认值
children 可以使用一个函数来代替 React 元素,通过调用这个函数与当前过渡状态(‘enter’、‘enter’、‘exit’、‘exited’、‘unmount’),可用于将特定于代码的props应用于组件。 Function element
in 用于显示组件;触发进入或退出状态。 boolean false
mountOnEnter 默认情况下,子组件与父转换组件一起立即挂载。如果你想“延迟挂载”第一个in={true}上的组件,你可以设置mountOnEnter。在第一次进入转换之后,组件将保持挂载状态,即使在“退出”状态下也是如此,除非你还指定unmountOnExit。 boolean false
unmountOnExit 默认情况下,子组件在达到“退出”状态后仍然挂载。如果你希望在组件退出后卸载组件,请设置unmountOnExit。 boolean false
appear 通常,如果组件挂载时显示组件,则该组件不进行转换。如果你希望在第一个挂载集上进行转换,则显示为true,并且组件将在< transition >挂载后立即进行转换。 注意:没有特定的“显示”状态。appear只添加一个额外的enter转换 boolean false
enter 启用或禁用enter转换。 boolean true
exit 启用或禁用exit转换。 boolean true
timeout 转换的持续时间,单位为毫秒。 number { enter?: number, exit?: number, appear?: number }
addEndListener 添加自定义转换结束触发器。使用正在转换的DOM节点和done回调调用。允许更细粒度的转换结束逻辑。注意:如果提供超时,仍将其用作回退。 Function
onEnter 在应用“输入”状态之前触发的回调。提供了一个额外的参数isAppearing,以指示是否在初始挂载上出现了enter阶段。 Function(node: HtmlElement, isAppearing: bool) function noop() {}
onEntering 在应用“输入”状态中触发的回调。提供了一个额外的参数isAppearing,以指示是否在初始挂载上出现了entering阶段。 Function(node: HtmlElement, isAppearing: bool) function noop() {}
onEntered 在应用“输入”状态之后触发的回调。提供了一个额外的参数isAppearing,以指示是否在初始挂载上出现了entered阶段。 Function(node: HtmlElement, isAppearing: bool) function noop() {}
onExit 在应用“退出”状态之前触发的回调。 Function(node: HtmlElement) -> void function noop() {}
onExiting 在应用“退出”状态中触发的回调。 Function(node: HtmlElement) -> void function noop() {}
onExited 在应用“退出”状态后触发的回调。 Function(node: HtmlElement) -> void function noop() {}

CSSTransition

此Transition组件用于CSS动画过渡,灵感来源于ng-animate库。

CSSTransition:在组件淡入appear,进场enter,出场exit时,CSSTransition组件应用了一系列className名来对这些动作进行描述。首先appear被应用到组件className上,接着添加“active”类名来激活CSS动画。在动画完成后,原class改变为done表明组件动画已经应用完成并加载完成。

当组件的in属性变为true时,组件的className将被赋值为example-enter,并在下一刻添加example-enter-active的CSS class名。这些都是基于className属性的约定。即:原组件带有className=”animate-rotate”,则enter状态时,变为”animate-rotate-enter”。

//index.js
import React,{ Component } from 'react'
import CSSTransition from 'react-transition-group/CSSTransition'
import './css/index.css'export default class App extends Component {
​
    state = {
        show: true
    }
​
    render () {
        return (
            <CSSTransition
                in={this.state.show}
                classNames='show'
                timeout={300}
                unmountOnExit>
                {state => {
                    // console.log(state)
                    return (
                        <div className='circle' onClick={()=>this.setState(state=>({show: !state.show}))}> 
                            show 
                        </div>
                    )
                }}
            </CSSTransition>
        )
    }
}
​
//index.css
.circle {
    margin: 2px;
    width: 50px;
    height: 50px;
    position: absolute;
    display: inline-block;
    left: 100px;
    box-shadow: 0px 1px 2px #999;
    text-shadow: 0px 1px 2px #999;
    line-height: 80px;
    text-align: center;
    color: white;
    font-size: 10px;
}
​
.show-enter {
    opacity: 0.01;
    transform: scale(0.9) translateY(50%);
  }
.show-enter-active {
    opacity: 1;
    transform: scale(1) translateY(0%);
    transition: all 300ms ease-out;
}
.show-exit {
    opacity: 1;
    transform: scale(1) translateY(0%);
}
.show-exit-active {
    opacity: 0.01;
    transform: scale(0.9) translateY(50%);
    transition: all 300ms ease-out;
}
复制代码
参数 说明 类型 默认值
in 控制组件应用动画的属性值,通常将一个react的组件state赋值给它,通过改变state,从而开启和关闭动画。 boolean false
classNames classNames[注意带s]属性用于当组件被应用动画时,不同的动画状态(enter,exits,done)将作为className属性的后缀来拼接为新的className。 如:className=”fade”会被应用为fade-enter,fade-enter-active,fade-enter-done,fade-exit,fade-exite-active,fade-exit-done, fade-appear以及fade-appear-active.每一个独立的className都对应着单独的状态。 string { appear?: string, appearActive?: string, enter?: string, enterActive?: string, enterDone?: string, exit?: string, exitActive?: string, exitDone?: string, }
onEnter 组件的回调函数,当组件enter或appear时会立即调用。 Function(node: HtmlElement, isAppearing: bool)
onEntering 组件的回调函数,当enter-active或appear-active时会立即调用。 Function(node: HtmlElement, isAppearing: bool)
onEntered 组件的回调函数,当组件的enter,appearclassName被移除时会立即调用。 Function(node: HtmlElement, isAppearing: bool)
onExit 当组件应用exit类名时,调用此函数。 Function(node: HtmlElement)
onExiting 当组件应用exit-active类名时,调用此函数。 Function(node: HtmlElement)
onExited 当组件exit类名被移除,且添加了exit-done类名时,调用此函数。 Function(node: HtmlElement)

SwitchTransition

受vue转换模式启发的转换组件。当你想要控制状态转换之间的呈现时,可以使用它。基于所选模式和子节点的键(Transition或cstransition组件),SwitchTransition在它们之间进行一致的转换。

如果选择了out-in模式,则SwitchTransition会等待旧的子节点离开,然后插入新的子节点。如果选择了in-out模式,SwitchTransition将首先插入一个新的子节点,等待新的子节点进入,然后删除旧的子节点。

注意:如果你想让动画同时发生(也就是说,移除旧的子元素并同时插入新的子元素),你应该使用TransitionGroup。

function App() {
 const [state, setState] = useState(false);
 return (
   <SwitchTransition>
     <CSSTransition
       key={state ? "Goodbye, world!" : "Hello, world!"}
       addEndListener={(node, done) => node.addEventListener("transitionend", done, false)}
       classNames='fade'
     >
       <button onClick={() => setState(state => !state)}>
         {state ? "Goodbye, world!" : "Hello, world!"}
       </button>
     </CSSTransition>
   </SwitchTransition>
 );
}
.fade-enter{
   opacity: 0;
}
.fade-exit{
   opacity: 1;
}
.fade-enter-active{
   opacity: 1;
}
.fade-exit-active{
   opacity: 0;
}
.fade-enter-active,
.fade-exit-active{
   transition: opacity 500ms;
}
复制代码
参数 说明 类型 默认值
mode 过渡模式。out-in:首先将当前元素移出,然后在完成时将新元素移入。in-out:新元素首先转换进来,完成后,当前元素转换出去。 out-in in-out
children 任何Transition 或者 CSSTransition组件. element

TransitionGroup

组件在一个列表中管理一组转换组件(< transition >和< cstransition >)。与转换组件一样,是一个状态机,用于管理组件随时间的挂载和卸载。

下面的例子,当项目被删除或添加到TodoList时,内部的prop将由自动切换。

注意没有定义任何动画行为!列表项的动画方式取决于各个转换组件。这意味着你可以混合和匹配不同列表项的动画。

//index.js
import React,{ Component } from 'react'
import { CSSTransition, TransitionGroup } from 'react-transition-group'
import './css/index.css'export default class App extends Component {
​
  state = {
    items: [
      { id: 1, text: 'Buy eggs' },
      { id: 2, text: 'Pay bills' },
      { id: 3, text: 'Invite friends over' },
      { id: 4, text: 'Fix the TV' },
    ]
  }
​
  render () {
    const { items } = this.state
    return (
      <div className='container'>
        <TransitionGroup className="todo-list">
          {items.map(({ id, text }) => (
            <CSSTransition
              key={id}
              timeout={500}
              classNames="show"
              unmountOnExit>
              <div className="todo-list-item">
                <button
                  className='cancle'
                  onClick={() => {
                    this.setState(state => ({
                      items: state.items.filter(
                        item => item.id !== id
                      ),
                    }));
                  }}>
                  &times;
                </button>
                <span className='item-text'>{text}</span>
              </div>
            </CSSTransition>
          ))}
        </TransitionGroup>
        <button
          className='add'
          onClick={() => {
            const text = prompt('Enter some text');
            if (text) {
              this.setState(state => ({
                items: [
                  ...state.items,
                  { id: 1123, text },
                ],
              }));
            }
          }}>
          Add Item
        </button>
      </div>
    )
  }
}
​
//index.css
.show-enter {
    opacity: 0.01;
  }
.show-enter-active {
    opacity: 1;
    transition: all 300ms ease-out;
}
.show-exit {
    opacity: 1;
}
.show-exit-active {
    opacity: 0.01;
    transition: all 300ms ease-out;
}
​
.container {
    position: absolute;
    top: 20px;
    left: 100px;
    padding: 20px;
    border-radius: 5px;
    box-shadow: 0 0 10px 1px rgb(202, 202, 202);
}
​
.todo-list {
    border-radius: 5px;
    box-shadow: 0 0 5px 1px rgb(202, 202, 202);
}
​
.todo-list-item {
    height: 35px;
    line-height: 35px;
    padding: 0 10px;
    border-bottom: 1px solid rgb(202, 202, 202);
}
​
.todo-list-item:last-of-type {
    border-bottom: 0;
}
​
.item-text {
    margin-left: 10px;
}
​
.cancle {
    border: 0;
    color: #fff;
    background-color: #F04134;
    border-radius: 3px;
    box-shadow: 0 0 5px 1px rgb(202, 202, 202);
}
​
.add {
    border: 0;
    height: 30px;
    line-height: 30x;
    width: 120px;
    margin-top: 15px;
    font-size: 14px;
    border-radius: 3px;
    box-shadow: 0 0 5px 1px rgb(202, 202, 202);
}
复制代码
参数 说明 类型 默认值
component default ‘div’ 也就是TransitionGroup渲染出来的标签为div,也可以就行更改,例如component=”span” 渲染出来的就是span标签。如果使用React v16+并且想要避免div元素的换行,你可以传入component={null}。 any div
children 其中给的组件,可以是字符串或者自定义组件等。 any
appear 为所有的child启用或禁用显示/appear动画。注意,指定此参数将覆盖在各个子转换上的任何默认设置。 boolean
enter 为所有的child启用或禁用进入/enter动画。注意,指定此参数将覆盖在各个子转换上的任何默认设置。 boolean
exit 为所有的child启用或禁用退出/exit动画。注意,指定此参数将覆盖在各个子转换上的任何默认设置。 boolean
childFactory 如果你需要在一个子节点离开时更新它可以提供一个childFactory来包装每个子节点,即使是那些将要离开的子节点。 Function(child: ReactElement) -> ReactElement child => child
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享