react过渡动画效果的实现,react-transition-group
本文介绍react相关的过渡动画效果的实现
有点类似vue的transition组件,主要用于组件mount和unmount之前切换时应用动画效果
安装
cnpm install react-transition-group --save
transition动画
import React from 'react' import ReactDOM from 'react-dom' import Transition from 'react-transition-group/Transition'; const duration = 300; const defaultStyle = { transition: `opacity ${duration}ms ease-in-out`, opacity: 0, width: "100px", height: "100px", background: "red" } const transitionStyles = { entering: { opacity: 0 }, entered: { opacity: 1 }, }; class MyComponent extends React.Component { constructor() { super(); this.state = { in: false } } toggleEnterState = () => { this.setState({in: !this.state.in}) } render() { return ( <div> <Transition in={this.state.in} timeout={1000} mountOnEnter={true} unmountOnExit={true}> {(state) => ( <div style={{ ...defaultStyle, ...transitionStyles[state] }}> I'm A fade Transition! </div> )} </Transition> <button onClick={this.toggleEnterState}>Click to Enter</button> </div> ) } } ReactDOM.render( <MyComponent/>, document.getElementById('root') )
transition动画配套api
** children 指的是Transition标签包含的待应用动画的元素,可以使用react的元素,也可以直接用函数,函数可以接受state参数 state的代表动画的4个状态 entering entered exiting exited ** in 应用于Transition标签上面,切换enter和exit,从而出现动画效果,布尔值 ** mountOnEnter 在元素enter的时候才挂载,布尔值 ** unmountOnExit 在元素exit的时候销毁,布尔值 ** appear 默认情况下Transition初次挂载的时候不应用动画 设置为apear之后,会自动应用一次enter动画 布尔值 ** enter 是否启用enter时候的动画,布尔值 作用和设置timeout为0一样 ** exit 是否启用exit时候的动画,布尔值 作用和设置timeout为0一样 ** timeout 过渡的持续时间,必须设置此值,除非addEventListener提供了 timeout = {500}或者 timeout = {{ enter: 300, exit: 500 }} ** addEndListener 用来监听dom节点的transition结束事件 addEndListener = { (node,done) => { node.addEventListener('transitionend', function(){ alert(111); }); done(); } } node是dom元素节点,done是切换状态的回调函数 ** onEnter 用来监听 enter 状态的钩子函数 onEnter={ (node,isAppearing) => {console.log(node,isAppearing) } node是dom节点 isAppearing是appear属性值 另外 onEntering 和 onEntered用法类似 ** onExit 用来监听 exit 状态开始触发的钩子函数 onExit={ (node) => {console.log(node) } 另外 onExiting 和 onExited 用法类似
animate动画
** index.js import React from 'react' import ReactDOM from 'react-dom' import { CSSTransition } from 'react-transition-group'; import './index.css'; const defaultStyle = { width: "100px", height: "100px", background: "red" } class MyComponent extends React.Component { constructor() { super(); this.state = { in: true } } toggleEnterState = () => { this.setState({in: !this.state.in}) } render() { return ( <div> <CSSTransition in={this.state.in} timeout={500} classNames='bounceInLeft'> {(state) => ( <div style={{ ...defaultStyle }}> I'm A fade Transition! </div> )} </CSSTransition> <button onClick={this.toggleEnterState}>Click to Enter</button> </div> ) } } ReactDOM.render( <MyComponent/>, document.getElementById('root') ) ** index.css @keyframes bounceInLeft { from, 60%, 75%, 90%, to { animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); } 0% { opacity: 0; transform: translate3d(-3000px, 0, 0); } 60% { opacity: 1; transform: translate3d(25px, 0, 0); } 75% { transform: translate3d(-10px, 0, 0); } 90% { transform: translate3d(5px, 0, 0); } to { transform: none; } } @keyframes bounceOutRight { 20% { opacity: 1; transform: translate3d(-20px, 0, 0); } to { opacity: 0; transform: translate3d(2000px, 0, 0); } } .bounceInLeft-enter{ animation: bounceInLeft 1s 1; } .bounceInLeft-exit{ animation: bounceOutRight 1s 1; }
animate动画配套api
** classNames 用在CSSTransition标签上面,自动添加状态后缀名 classNames = "demo"; 会依次应用 demo-enter,demo-enter-active,demo-exit,demo-exit-active,demo-appear,demo-appear-active 如果单独制定class的name的话可以使用如下 classNames = {{ appear: 'demo1', appearActive: 'demo2', enter: 'demo3', enterActive: 'demo4', exit: 'demo5', exitActive: 'demo6' }} ** onEnter 在enter或者appear类应用完成后立马调用回调函数 onEnter={ (node,isAppearing) => {console.log(node,isAppearing)} } ** onEntering 在enter-active或者appear-active应用完成后立马调用回调函数 onEntering={ (node,isAppearing) => {console.log(node,isAppearing)} } ** onEntered 在enter或者appear移除完成后立马调用回调函数 onEntered={ (node,isAppearing) => {console.log(node,isAppearing)} } ** onExit 在exit类应用完成后立即调用回调函数 onEntered={ (node) => {console.log(node)} } ** onExiting 在exit-active类应用完成后立即调用回调函数 onExiting={ (node) => {console.log(node)} } ** onExited 在exit类移除后立即调用 onExited={ (node) => {console.log(node)} }
TransitionGroup
专门处理列表动画而诞生的组件,只要在TransitionGroup中的元素减少或者增加,自动为Transition或者CSSTransition应用in属性 import React from 'react' import ReactDOM from 'react-dom' import Transition from 'react-transition-group/Transition'; import {TransitionGroup} from 'react-transition-group' const duration = 300; const defaultStyle = { transition: `opacity ${duration}ms ease-in-out`, opacity: 0, width: "100px", height: "100px", background: "red" } const transitionStyles = { entering: { opacity: 0 }, entered: { opacity: 1 }, }; class MyComponent extends React.Component { constructor() { super(); this.state = { arr: ['a','c','d','e'] } } addItem = () => { this.setState({ arr: this.state.arr.concat(['f']) }); } render() { return ( <div> <TransitionGroup component="span" appear> {this.state.arr.map( (item,index) => ( <Transition key={index} timeout={0}> {(state) => ( <div style={{ ...defaultStyle, ...transitionStyles[state] }}> {item} </div> )} </Transition> ) )} </TransitionGroup> <button onClick={this.addItem}>添加元素</button> </div> ) } } ReactDOM.render( <MyComponent/>, document.getElementById('root') )
TransitionGroup配套api
** component 默认TransitionGroup是渲染成div,可以通过指定component改变这一默认行为 ** appear 是否执行初次渲染enter动画 ** enter 是否开启enter动画 ** exit 是否开启exit动画 ** childFactory 此函数是TransitionGroup将要展示子元素的拦截器 childFactory={(el) => {console.log(el);return el}}