ReactJS - 动画



动画是现代 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 样式的选项,并在元素从一个状态移动到另一个状态时根据样式对元素进行动画处理。该库在 props 中提供了用于设置元素的当前状态。如果 in props 值为 true,则表示元素正在从进入状态变为退出状态。如果 in props 值为 false,则表示元素正在从退出移动到退出。

安装

要安装此 React Transition Group 库,请使用以下任一命令 -


# npm
npm install react-transition-group --save

# yarn
yarn add react-transition-group

过渡

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

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

接下来,安装 React Transition Group 库。

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

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

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

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

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

接下来,导入 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 (	
	 	);	
}

接下来,添加 Transition 组件。使用 this.state.inProp 表示 in prop,使用 this.duration 表示超时属性。Transition 组件需要一个函数,该函数返回用户界面。它基本上是一个渲染道具。


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

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


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;

接下来,创建一个文件,index.js src 文件夹下并使用 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')
);

最后,在根文件夹下创建一个公共文件夹,并创建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 商店中删除该项目。

动画

要了解有关使用 React Transition Group 为元素制作动画的更多信息,请单击此处。

CSS搜索

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

例如,classNames=你好 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 应用程序。

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


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

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

接下来,导入 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 prop,使用 this.duration 表示超时属性,使用 你好 表示 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;

接下来,创建一个文件,index.js src 文件夹下并使用 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>