动画可以让用户体验变得更加流畅自然,而React的TransitionGroup插件配合CSS3可以让我们在项目中整合动画效果的变得易如反掌。
通常情况下,浏览器中的动画都拥有一套极其命令式的API,你需要选择一个元素并主动移动它或者改变它的样式,已实现动画效果。这种渲染方式显得格格不入,因此React选择了一种偏声明式的方法实现动画。
CSS渐变组(CSS Transition Group)会在何时的渲染及重渲染时间点有策略地添加和移动元素的class,以此来简化将CSS动画应用于渐变的过程,这意味着唯一需要你万郴的任务就是给这些class写明合适的样式。
间隔渲染以牺牲性能为代价提供饿了更多的扩展性和可控性。这种方法选哟更多次的渲染,但同时也允许你为CSS之外的内容,(比如滚动条位置及Canvas绘画)添加动画。
一、CSS渐变组:
<ReactCSSTransitionGrouptransitionName='question'>
{questions}
</ReactCSSTransitionGroup>
ReactCSSTransitionGroup 是一款插件,它在文件最顶部通过var ReactCSSTransitionGroup =React.addons.ReactCSSTransitionGroup;语句引入。
它会自动在核实的时候处理组件重渲染,同时根据当前的渐变状态调整渐变组的class以便实现组件样式的改变。
二、给渐变的class添加样式
为元素添加transitionName =‘question’意味着给它添加饿了4个question-enter、question-enter-active、question-leave及question-leave-active。当子组件进入或者退出ReactCSSTranstionGroup时,CSSTransitionGroup插件会自动添加或移除这些Class。
以下是问卷编辑器中使用到的渐变样式:
.survey-editor.question-enter{
transform:scale(1.2);
transition:transform 0.2s cubic-bezier(.97,.84,.5,1.21);
}
.survey-editor.question-enter-active{
transform:scale(1);
}
.survey-editor.question-leave{
transform:translateY(0);
opacity:0;
transition:opacity 1.25,transgorm 1scubic-bezier(.52,-0.25,.52,.95);
}
.survey-editor.question-leave-active{
opacity:0;
transform:translateY(-100%);
}
三、渐变生命周期:
question-enter与question-enter-active的区别在于,question-enter这个class是组件被添加到渐变组后即可添加上的,而question-enter-active则是在下一轮渲染时添加的,这样设计让你能轻松的定义渐变开始时候的样式,结束时候的样式以及如何进行渐变。
例如:当问卷调查器重的问题被添加到列表的时候他们首先用scale(1.2)进行发大,然后渐变到正常的scale(1)状态,总共花了0.2秒,这就创造出了一种你看到的跳出来的效果。默认情况下,渐变组同事开启了进入和退出的动画,你可以通过给组件添加transitionEnter={false}或tranitionLeave={false}属性来禁用其中一个或全部禁用,除了可以控制选择哪些动画外,我们还能根据一个可配置 的值在特定的情况下禁用动画,像是这样:
<ReactCSSTransitionGrouptransitionName='question'
transitionEnter={this.props.enableAnimations}
transitionLeave={this.props.enableAnimations}
{questions}
</ReactCSSTransitionGroup>
使用渐变组主要有两个重要的隐患需要注意,
首先,渐变组会延迟子组件的移除直到动画完成,这意味着如果你把一个列表的组件包裹进一个ReactCSSTransitionGroup中,去没有trasitionName属性指定的class明确任何CSS,这些组件将无法被移除——甚至当你尝试不再渲染它们时也不可以。
其次渐变组每一个子组件都必须设置一个独一无二的key属性,渐变组使用这个属性来判断组件究竟是进入还是退出,因为如果没有设置key属性动画可能无法执行,同时组件会变得无法移除。
注意,即使渐变组只有一个子元素,它也需要设置一个key属性。
四、间隔渲染:
使用CSS3动画能够获得巨大的性能提升并拥有简洁的代码,但他们并不总是解决问题的正确工具,有些时候,你必须为比较老,不支持CSS3的浏览器做兼容,还有些时候你想为CSS属性之外的东西添加动画,比如滚动条位置和Canvas绘画,这些情况下,间隔渲染能够满足我们的要求,但是相比CSS3动画来说,它会带来一定的性能损耗。
间隔渲染最基本的思想就是周期性的触发组件状态更新,以明确当前处于整个动画时间中的什么阶段。通古总组件的render方法中加入这个状态值,组件可以每次状态更新出发渲染中正确的表示当前的动画阶段。
因为这种方法设计多次重渲染,所以通常最好和requestAnimationFrame一起使用以避免不必要的渲染,不过在requestAnimationFrame不被支持或不可用的情况下,降级到不那么智能的setTimeout就是唯一的选择了。
五、使用requestAnimationFrame实现间隔渲染
假设你希望使用间隔渲染将一个div从屏幕的一边移动到另一边,可以同故宫给他添加position:absolute并随着时间变化不停的更新left属性或者top属性来实现,根据消耗时间内的变化总量,用requestAnimationFrame来实现这个动画应该可以得出一个流畅的动画。
六、使用setTimeout实现间隔渲染
尽管requestAnimatingFrame总体上能狗以最小的性能损耗实现最流畅的动画,但它在比较老的浏览器上无法使用的,而且它被调用的次数可能比你想象的更频繁(也更加无法预测)。这些情况下你可以使用setTimout。
总结:
1、在状态改变过程中,使用CSS3和渐变组高效的应用渐变动画。
2、使用requestAnimationFrame为CSS之外的东西添加动画,如滚动条位置或者Canvas绘画。
3、当requestAnimationFrame不被支持时降级到setTimeout方法。