ReactJS – Animation动画

动画是现代 Web 应用程序的一个令人兴奋的功能。它给应用程序带来了清爽的感觉。React 社区提供了许多优秀的基于 React 的动画库,如 React Motion、React Reveal、react-animations 等,React 本身提供了一个动画库,React Transition Group作为附加选项更早。它是一个独立的库,增强了该库的早期版本。让我们在本章学习 React Transition Group 动画库。

React过渡组

React Transition Group库是一个简单的动画实现。它不做任何开箱即用的动画。相反,它公开了核心动画相关信息。每个动画基本上都是元素从一种状态到另一种状态的过渡。该库公开了每个元素的最小可能状态,它们在下面给出 –

  • 进入Entering
  • 进入Entered
  • 退出Exiting
  • 退出Exited

该库提供了为每个状态设置 CSS 样式的选项,并在元素从一种状态移动到另一种状态时根据样式为元素设置动画。该库提供了道具来设置元素的当前状态。如果in props 值为 true,则表示元素正在从进入状态移动到退出状态。如果 in props 的值为 false,则表示元素正在从退出移动到退出。

过渡

过渡React 过渡组提供的用于动画元素的基本组件。让我们创建一个简单的应用程序并尝试使用Transition 元素淡入/淡出元素。

首先,按照创建 React 应用程序章节中的说明,使用Create React AppRollup bundler创建一个新的 react 应用程序react-animation-app 。

接下来,安装React Transition Group库。

cd /go/to/project 
npm install react-transition-group --save

接下来,在您喜欢的编辑器中打开应用程序。

接下来,在应用程序的根目录下创建 src 文件夹。

接下来,在src文件夹下创建components文件夹。

接下来,在src/components文件夹下创建一个文件HelloWorld.js并开始编辑。

接下来,导入React和动画库。

import React from 'react'; 
import { Transition } from 'react-transition-group'

接下来,创建HelloWorld组件。

class HelloWorld extends React.Component {
   constructor(props) {
      super(props);
   }
}

接下来,在构造函数中将与过渡相关的样式定义为 JavaScript 对象。

this.duration = 2000;
this.defaultStyle = {
   transition: `opacity ${this.duration}ms ease-in-out`,
   opacity: 0,
}
this.transitionStyles = {
   entering: { opacity: 1 },
   entered: { opacity: 1 },
   exiting: { opacity: 0 },
   exited: { opacity: 0 },
};

这里,

  • defaultStyles设置过渡动画
  • transitionStyles设置各种状态的样式

接下来,在构造函数中设置元素的初始状态。

this.state = { 
   inProp: true 
}

接下来,通过每 3 秒更改一次inProp值来模拟动画。

setInterval(() => {
   this.setState((state, props) => {
      let newState = {
         inProp: !state.inProp
      };
      return newState;
   })
}, 3000);

接下来,创建一个渲染函数。

render() { 
   return ( 
   ); 
}

接下来,添加过渡组件。将this.state.inProp用于in道具,将 this.duration用于timeout 道具。转换组件需要一个返回用户界面的函数。它基本上是一个渲染道具

render() {
   return (
      <Transition in={this.state.inProp} timeout={this.duration}>
         {state => ({
            ... component's user interface.
         })
      </Transition>
   );
}

接下来,在容器内编写组件用户界面,并为容器设置defaultStyletransitionStyles

render() {
   return (
      <Transition in={this.state.inProp} timeout={this.duration}>
         {state => (
            <div style={{
               ...this.defaultStyle,
               ...this.transitionStyles[state]
            }}>
               <h1>Hello World!</h1>
            </div>
         )}
      </Transition>
   );
}

最后,暴露组件。

export default HelloWorld

该组件的完整源代码如下 –

import React from "react";
import { Transition } from 'react-transition-group';

class HelloWorld extends React.Component {
   constructor(props) {
      super(props);
      this.duration = 2000;
      this.defaultStyle = {
         transition: `opacity ${this.duration}ms ease-in-out`,
         opacity: 0,
      }
      this.transitionStyles = {
         entering: { opacity: 1 },
         entered: { opacity: 1 },
         exiting: { opacity: 0 },
         exited: { opacity: 0 },
      };
      this.state = {
         inProp: true
      }
      setInterval(() => {
         this.setState((state, props) => {
            let newState = {
               inProp: !state.inProp
            };
            return newState;
         })
      }, 3000);
   }
   render() {
      return (
         <Transition in={this.state.inProp} timeout={this.duration}>
            {state => (
               <div style={{
                  ...this.defaultStyle,
                  ...this.transitionStyles[state]
               }}>
                  <h1>Hello World!</h1>
               </div>
            )}
         </Transition>
      );
   }
}
export default HelloWorld;

接下来,在src文件夹下创建一个文件index.js并使用HelloWorld组件。

import React from 'react';
import ReactDOM from 'react-dom';
import HelloWorld from './components/HelloWorld';

ReactDOM.render(
   <React.StrictMode   
      <HelloWorld /   
   </React.StrictMode   ,
   document.getElementById('root')
);

最后,在根文件夹下创建一个public文件夹,并创建index.html文件。

<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="utf-8">
      <title>React Containment App</title>
   </head>
   <body>
      <div id="root"></div>
      <script type="text/JavaScript" src="./index.js"></script>
   </body>
</html>

接下来,使用 npm 命令为应用程序提供服务。

npm start

接下来,打开浏览器,在地址栏输入http://localhost:3000,回车。

单击删除链接将从 redux 商店中删除该项目。

CSS过渡

CSSTransition建立在Transition组件之上,它通过引入classNames属性改进了Transition组件。classNames属性是指用于元素各种状态的 css 类名。

例如,classNames=hello prop 引用下面的 css 类。

.hello-enter {
   opacity: 0;
}
.hello-enter-active {
   opacity: 1;
   transition: opacity 200ms;
}
.hello-exit {
   opacity: 1;
}
.hello-exit-active {
   opacity: 0;
   transition: opacity 200ms;
}

让我们使用CSSTransition组件创建一个新组件HelloWorldCSSTransition

首先,在您喜欢的编辑器中打开我们的react-animation-app 应用程序。

接下来,在src/components文件夹下创建一个新文件HelloWorldCSSTransition.css并输入过渡类。

.hello-enter {
   opacity: 1;
   transition: opacity 2000ms ease-in-out;
}
.hello-enter-active {
   opacity: 1;
   transition: opacity 2000ms ease-in-out;
}
.hello-exit {
   opacity: 0;
   transition: opacity 2000ms ease-in-out;
}
.hello-exit-active {
   opacity: 0;
   transition: opacity 2000ms ease-in-out;
}

接下来,在src/components文件夹下创建一个新文件HelloWorldCSSTransition.js并开始编辑。

接下来,导入React和动画库。

import React from 'react'; 
import { CSSTransition } from 'react-transition-group'

接下来,导入HelloWorldCSSTransition.css

import './HelloWorldCSSTransition.css'

接下来,创建HelloWorld组件。

class HelloWorldCSSTransition extends React.Component {
   constructor(props) {
      super(props);
   }
}

接下来,在构造函数中定义转换的持续时间。

this.duration = 2000;

接下来,在构造函数中设置元素的初始状态。

this.state = { 
   inProp: true 
}

接下来,通过每 3 秒更改一次 inProp 值来模拟动画。

setInterval(() => {
   this.setState((state, props) => {
      let newState = {
         inProp: !state.inProp
      };
      return newState;
   })
}, 3000);

接下来,创建一个渲染函数。

render() { 
   return (
   ); 
}

接下来,添加CSSTransition组件。将this.state.inProp用于 in 属性,this.duration用于timeout属性,将hello用于classNames属性。CSSTransition组件期望用户界面作为子道具。

render() {
   return (
      <CSSTransition in={this.state.inProp} timeout={this.duration} 
         classNames="hello">
         // ... user interface code ...   
      </CSSTransition>
   );
}

接下来,编写组件用户界面。

render() {
   return (
       <CSSTransition in={this.state.inProp} timeout={this.duration} 
      classNames="hello">
      <div>
          <h1>Hello World!</h1>
      </div>
       </CSSTransition>
   );
}

最后,暴露组件。

export default HelloWorldCSSTransition;

该组件的完整源代码如下 –

import React from 'react';
import { CSSTransition } from 'react-transition-group'
import './HelloWorldCSSTransition.css' 

class HelloWorldCSSTransition extends React.Component {
   constructor(props) {
      super(props);
      this.duration = 2000;
      this.state = {
         inProp: true
      }
      setInterval(() => {
         this.setState((state, props) => {
            let newState = {
               inProp: !state.inProp
            };
            return newState;
         })
      }, 3000);
   }
   render() {
      return (
         <CSSTransition in={this.state.inProp} timeout={this.duration} 
            classNames="hello">
            <div>
               <h1>Hello World!</h1>
            </div>
         </CSSTransition>
      );
   }
}
export default HelloWorldCSSTransition;

接下来,在src文件夹下创建一个文件index.js并使用HelloWorld组件。

import React from 'react';
import ReactDOM from 'react-dom';
import HelloWorldCSSTransition from './components/HelloWorldCSSTransition';

ReactDOM.render(
   <React.StrictMode>
      <HelloWorldCSSTransition />
   </React.StrictMode>,
   document.getElementById('root')
);

接下来,使用 npm 命令为应用程序提供服务。

npm start

接下来,打开浏览器,在地址栏输入http://localhost:3000,回车。

消息将每 3 秒淡入淡出。

过渡组

TransitionGroup是一个容器组件,它管理一个列表中的多个过渡组件。例如,虽然列表中的每个项目都使用CSSTransition,但 TransitionGroup可用于对所有项目进行分组以获得正确的动画效果。

<TransitionGroup>
   {items.map(({ id, text }) => (
      <CSSTransition key={id} timeout={500} classNames="item" >
         <Button
            onClick={() =>
               setItems(items =>
                  items.filter(item => item.id !== id)
               )
            }
            >
            &times;
         </Button>
         {text}
      </CSSTransition>
   ))}
</TransitionGroup>