React过渡动画 安装react-transition-group # npm npm install react-transition-group --save # yarn yarn add react-transition-group
可导入使用的有四个组件对象:
Transition(不常用) CSSTransition(它的属性结合css控制组件出现、消失) SwitchTransition(控制两个组件之间状态切换) TransitionGroup(当有一组组件的动画时,需要使用它包裹) 使用CSSTransition 1】首先写css类名样式 CSSTransition执行过程中,有三个状态:appear、enter、exit; 它们有三种状态,需要定义对应的CSS样式:第一类,开始状态:对于的类是-appear、-enter、-exit; 第二类:执行动画:对应的类是-appear-active、-enter-active、-exit-active; 第三类:执行结束:对应的类是-appear-done、-enter-done、-exit-done; .card-enter, .card-appear {opacity: 0;transform: scale(.8);}.card-enter-active, .card-appear-active {opacity: 1;transform: scale(1);transition: opacity 300ms, transform 300ms;}.card-exit {opacity: 1;}.card-exit-active {opacity: 0;transform: scale(.8);transition: opacity 300ms, transform 300ms;}
2】CSSTransition组件属性 in:触发进入或者退出状态如果添加了unmountOnExit={true}
,那么该组件会在执行退出动画结束后被移除掉; 当in为true时,触发进入状态,会添加-enter、-enter-acitve的class开始执行动画,当动画执行结束后,会移除两个class,并且添加-enter-done的class; 当in为false时,触发退出状态,会添加-exit、-exit-active的class开始执行动画,当动画执行结束后,会移除两个class,并且添加-enter-done的class; classNames:动画class的名称决定了在编写css时,对应的class名称:比如card-enter、card-enter-active、card-enter-done; timeout: appear:是否在初次进入添加动画(需要和in同时为true) 其他属性可以参考官网来学习:https://reactcommunity.org/react-transition-group/transition CSSTransition对应的钩子函数:主要为了检测动画的执行过程,来完成一些Javascript的操作
onEnter:在进入动画之前被触发; onEntering:在应用进入动画时被触发; onEntered:在应用进入动画结束后被触发; import React, { Component } from 'react' import { CSSTransition } from 'react-transition-group'; import '../style/ReactTransition.css'interface IProps { } interface IState {isShowCard: boolean } class ReactTransition extends Component {constructor(props) {super(props)this.state = {isShowCard: true}}render() {return ( this.setState({ isShowCard: !this.state.isShowCard })}>显示/隐藏 哈哈哈
)} }export default ReactTransition
使用SwitchTransition SwitchTransition可以完成两个组件之间切换的炫酷动画:
比如我们有一个按钮需要在on和off之间切换,我们希望看到on先从左侧退出,off再从右侧进入; 这个动画在vue中被称之为 vue transition modes; react-transition-group中使用SwitchTransition来实现该动画; SwitchTransition中主要有一个属性:mode ,有两个值
in-out:表示新组件先进入,旧组件再移除; out-in:表示就组件先移除,新组建再进入; SwitchTransition还是需要通过CSSTransition来进行控制,使用key属性来控制(不能使用in属性)
SwitchTransition组件里面要有CSSTransition或者Transition组件,不能直接包裹你想要切换的组件; SwitchTransition里面的CSSTransition或Transition组件不再像以前那样接受in属性来判断元素是何种状态,取而代之的是key属性; import React, { Component } from 'react' import { CSSTransition, SwitchTransition } from 'react-transition-group'; import '../style/ReactTransitionSwitch.css'interface IProps {} interface IState {isOn: boolean } class ReactTransitionSwitch extends Component {constructor(props: IProps) {super(props)this.state = {isOn: true}}render() {const { isOn } = this.state;return ({ {this.setState({ isOn: !isOn })}}>{isOn ? "on" : "off"} }
)} }export default ReactTransitionSwitch
ReactTransitionSwitch.css
.btn-enter {transform: translate(100%, 0);opacity: 0; }.btn-enter-active {transform: translate(0, 0);opacity: 1;transition: all 500ms; }.btn-exit {transform: translate(0, 0);opacity: 1; }.btn-exit-active {transform: translate(-100%, 0);opacity: 0;transition: all 500ms; }
使用TransitionGroup 当我们有一组动画时,需要将这些CSSTransition放入到一个TransitionGroup中来完成动画:
import React, { PureComponent } from 'react' import { CSSTransition, TransitionGroup } from 'react-transition-group'; import '../style/ReactTransitionGroup.css';interface Iprops {} interface Istate {friends: Array,count: number } class ReactTransitionGroup extends PureComponent {constructor(props: Iprops) {super(props);this.state = {friends: [],count: 0}}render() {return ({this.state.friends.map((item, index) => {return ({item} {let friends = [...this.state.friends]friends.splice(index, 1)this.setState({ friends: friends })}}>×
)})} {this.setState({friends: [...this.state.friends, (this.state.count + 1).toString()],count: this.state.count + 1})}}>+friend )} } export default ReactTransitionGroup
ReactTransitionGroup.css
.friend-enter {opacity: 0; }.friend-enter-active {opacity: 1;transition: opacity 500ms ease-in; }.friend-exit {opacity: 1; }.friend-exit-active {opacity: 0;transition: opacity 500ms ease-in; }.buttonAdd {position: absolute;top: 50%;left: 55%; }