文章源自: https://facebook.github.io/react/docs/animation.htmlcss
ReactCSSTransitionGroup
基於 ReactTransitionGroup
,當一個React組件enter或者leave時能夠方便的用來執行CSS transitions和animations。html
import ReactCSSTransitionGroup from 'react-addons-css-transition-group' // ES6 var ReactCSSTransitionGroup = require('react-addons-css-transition-group') // ES5 with npm var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup; // ES5 with react-with-addons.js
var React = require('react'); var ReactDOM = require('react-dom'); var CSSTransitionGroup = require('react-addons-css-transition-group'); var INTERVAL = 2000; var AnimateDemo = React.createClass({ getInitialState: function() { return {current: 0}; }, componentDidMount: function() { this.interval = setInterval(this.tick, INTERVAL); }, componentWillUnmount: function() { clearInterval(this.interval); }, tick: function() { this.setState({current: this.state.current + 1}); }, render: function() { var children = []; var pos = 0; var colors = ['red', 'gray', 'blue']; for (var i = this.state.current; i < this.state.current + colors.length; i++) { var style = { left: pos * 128, background: colors[i % colors.length] }; pos++; children.push(<div key={i} className="animateItem" style={style}>{i}</div>); } return ( <CSSTransitionGroup className="animateExample" transitionEnterTimeout={1500} transitionLeaveTimeout={1500} transitionName="example"> {children} </CSSTransitionGroup> ); } });
注意: 必須給 ReactCSSTransitionGroup 中的每個child設置一個key屬性,即便只渲染一個element
!react
在這個組件中,當添加一個元素到 ReactCSSTransitionGroup 中時,這個元素將會自動添加上
example-enter
和 example-enter-active
樣式。添加上的樣式基於 transitionName 這個屬性來設置。
咱們須要作的就是定義example-xxx等樣式;git
.example-enter, .example-leave { -webkit-transition: all 2s; transition: all 2s; } .example-enter { /* begin **/ opacity: 0.01; margin-left: 128px; } .example-enter.example-enter-active { /* finish **/ opacity: 1; margin-left: 0; } .example-leave { opacity: 1; margin-left: 0; } .example-leave.example-leave-active { opacity: 0.01; margin-left: -128px; } .animateExample { display: block; height: 128px; position: relative; width: 384px; } .animateItem { color: white; font-size: 36px; font-weight: bold; height: 128px; line-height: 128px; position: absolute; text-align: center; -webkit-transition: all 1s; /* TODO: make this a move animation */ transition: all 1s; /* TODO: make this a move animation */ width: 128px; }
example-enter和example-enter-active分別表示動畫開始和動畫結束時的樣式定義;github
動畫時間在css樣式表中和render方法中,都必須指定,時間用來告訴React何時去移除animation樣式以及何時從DOM中移除元素。web
ReactCSSTransitionGroup 提供了可選的屬性 transitionAppear ,用來指定組件初始加載時的動畫,該屬性默認值是false,因此在組件加載的時候默認是沒有動畫的; npm
return ( <CSSTransitionGroup className="animateExample" transitionAppear={true} transitionAppearTimeout={1500} transitionEnterTimeout={1500} transitionLeaveTimeout={1500} transitionName="example"> {children} </CSSTransitionGroup> );
修改組件的render方法,而且在css中定義example-appear, example-appear-active樣式;api
.example-appear { opacity: 0.01; margin-left: 128px; } .example-appear.example-appear-active { opacity: 1; margin-left: 0; }
這樣在組件初始加載的時候,也會有動畫了!app
組件第一次加載的時候,執行的動畫是appear,以後再有element動態添加到CSSTransitionGroup,將會執行enter動畫,而不會是appear動畫;dom
transitionEnter和transitionLeave默認值是true,因此若是不把它們指定爲false的話得指定transitionEnterTimeout和transitionLeaveTimeout。
除了經過transitionName指定樣式,還能夠指定每一步的動畫樣式,其中,active樣式名能夠不用指定;
// ... <ReactCSSTransitionGroup transitionName={ { enter: 'enter', enterActive: 'enterActive', leave: 'leave', leaveActive: 'leaveActive', appear: 'appear', appearActive: 'appearActive' } }> {item} </ReactCSSTransitionGroup> <ReactCSSTransitionGroup transitionName={ { enter: 'enter', leave: 'leave', appear: 'appear' } }> {item2} </ReactCSSTransitionGroup> // ...
上面所實現的動畫,都是整個Group中的元素都將被設置動畫,實際上還能夠指定只須要某一/零個元素執行動畫;
import ReactCSSTransitionGroup from 'react-addons-css-transition-group'; function ImageCarousel(props) { return ( <div> <ReactCSSTransitionGroup transitionName="carousel" transitionEnterTimeout={300} transitionLeaveTimeout={300}> <img src={props.imageSrc} key={props.imageSrc} /> </ReactCSSTransitionGroup> </div> ); }
爲了組child添加動畫屬性,ReactCSSTransitionGroup
必須已經被加載到DOM中,或者將 transitionAppear
設置成true。
render() { const items = this.state.items.map((item, i) => ( <div key={item} onClick={() => this.handleRemove(i)}> <ReactCSSTransitionGroup transitionName="example"> {item} </ReactCSSTransitionGroup> </div> )); return ( <div> <button onClick={this.handleAdd}>Add Item</button> {items} </div> ); }
上面這個例子將不會起做用,由於ReactCSSTransitionGroup
被加載到新的div中,而不是已經加載好的元素當中,且沒有設置transitionAppear。
還能夠禁止掉enter或者是leave動畫,好比但願有enter動畫而不想要leave動畫,可是ReactCSSTransitionGroup須要等待動畫完成後才從dom中remove元素,此時能夠經過設置transitionEnter={false}或者transitionLeave={false}來禁止相應的動畫;
在ReactCSSTransitionGroup中,沒有動畫完成的監聽,因此若是想要獲取到動畫的執行進度而且添加其它操做是不可行的,若是確實有須要,可使用ReactTransitionGroup;