这里只讨论React的一个动画插件提供的动画机制,其他的通过自己写JS操作的动画都是一样的,和React没啥关系。
React.addons.CSSTransitionGroup 提供了一个分组动画,所谓分组动画就是指它可以对一个数组中的元素的增加和减少做一个动画。
比如我们通过一个数组来渲染一个列表,那么当列表增加或者减少的时候我们可以定义他的动画。
动画原理
React.addons.CSSTransitionGroup
的原理非常简单,通过 CSSTransitionGroup
标签来指定对一个DOM列表进行动画操作,通过 transitionName='my-animate-name'
来指定动画的名称。
当增加一项时,会自动在增加的那一项上增加两个类: {name}-enter
和 {name}-enter-active
。CSS动画执行结束之后这两个类会被删掉。其中 {name}-enter
会在 {name}-enter-active
的前一帧被加上。因此 {name}-enter
用来定义动画的初始状态,{name}-enter-active
用来定义动画的结束状态。
当减少一项时,会自动在删除之前增加一个 {name}-leave
和 {name}-leave-active
类,这俩着的区别和前面的是一样的。
所以可以通过CSS3来写动画。
简单示例
我们来写一个简单的动画示例。显示一个学生列表,然后定时增加一条,在增加的时候使用一个fade动画。点击的时候做一个放大并渐变的消失动画:
下面是JSX代码:
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup; var Students = React.createClass({ getInitialState: function() { return { students: ['amy','bob','tom','lucy'] }; },componentDidMount: function() { var self = this; var update = function() { self.setState({ students: self.state.students.concat(["unamed-"+parseInt(Math.random()*10000000)]) }); } setInterval(update,1000); },handleRemove: function(e) { var name = $(e.target).data("name"); var index = 0; var students = this.state.students; for(var i=0;i<students.length;i++) { if(students[i] == name) index = i; } var state = this.state.students.splice(index,1); this.setState({ state: state }); },render: function() { var s = this.state.students; var self = this; return ( <div> <ReactCSSTransitionGroup transitionName="student"> { s.map(function(d,i) { return <div className='student' key={d}>{d} <a onClick={self.handleRemove} data-name={d}>删除</a></div> }) } </ReactCSSTransitionGroup> </div> ); } }); React.render( <Students />,document.getElementById("div1") );
下面是css代码:
.student { float: left; margin: 20px; } .student-enter { opacity: .2; transition: opacity 1s; } .student-enter-active { opacity: 1; } .student-leave { transform: scale(1); opacity: 1; transition: all .5s ease-in; } .student-leave-active { transform: scale(5); opacity: 0; }