Animate
我们一直强调体验,从用户的感受出发,站在技术的角度来讲,好的体验大约应该包含2点:快,炫! 快要求硬件,网络,代码等因素表现优秀。而炫,大约就要体现在“动画”上了。
优秀的前端工程师偶尔会表现出对CSS,对动画的“嗤之以鼻”,大约是以为这些是奇淫巧计,没什么可研究的,又或许是因缺少美感而无感。 不无遗憾。
这篇文章是我们在实践react时,对如何应用动画的一点思考。我们希望我们的使用方式能够更加“react化”。这是一篇使用层面上的指南,而非技术点的深究,会介绍若干已有的解决方案,适合想在react中使用动画的开发者阅读。文中观点不免浅薄,如有误读,请指正。
归根到底,动画有2种实现方案,一种CSS法,一种JS法。 CSS法,通过CSS的transition属性设置动画效果。要求“同一个元素”在相同的属性上有可以“衡量”的变化,比如由100px变为200px,这样CSS可以在规定的时间内做线性的变化,从而实现动画效果。但是像display:block到inline这种变化,就是不可衡量的,CSS不知道让这种变化如何以时间维度而变化。
//html
<div>some thing</div>
//js
$('div').addClass('tall')
//CSS
div {
height: 100px;
transition: 1s;
}
div .tall {
height: 200px;
}
JS法,通过一点点改变属性的值来实现动画,由JS来控制时间与变化的关系。以jQuery为例,传统的方法就是选节点,让jquery一点点变化。
$('#element'). animate({
height:'200px',
}, 1000, callback);
那么,在react中,我们如何地道地给元素加动画呢? 以经典的ToDoList为例,我们考虑2个场景: 添加一个项目,样式上表现为“高度由0变为100px" 完成一个,将其置为已完成状态,样式上表现为“由黑色一点点变为灰色”
场景一:添加一个项目 我们通过this.state.list管理列表,添加一个项目时,直接在数据层面上向this.state.list中追加一项,state的变化会自动的触发render,渲染出一个新的项目。这时我们想给这一项添加动画,如何做到? 我们不再拥有那个时机,创建新的节点item,将其append到list上,同时为item设置动画。
对于这种MVVM的框架如何应用动画,Angular和react都提出了相似的解决方案。
Angular认为具有动画属性的directive(可以认为是一些基础组件),至多有3种动画状态:enter,move,leave,Angular分别提供CSS,JS,CSS+JS方式。添加一个项目对应”enter"动画,CSS方式上为新加的项目添加ng-enter,ng-enter-active类,用户可以利用类的变化而设置动画:
.item .ng-enter{
transition:0.5s linear all;
height: 0px;
}
.item .ng-enter.ng-enter-active {
height: 100px;
}
同时也可以通过JS方式管理:
myModule.animation('.item', [function() {
return {
enter: function(element, doneFn) {
jQuery(element).animate( height:'100px'}, 1000, doneFn);
},
}
}]);
类似地,react也提出了类似的解决方案,她也提出3中动画状态:enter,appear,leave,而其实enter ≈ appear。react也提供了CSS,JS管理方式,CSS上同Angular,也是用类来识别,JS上则加入了“生命周期”函数,与Angular殊途同归:
var TodoList = React.createClass({
componentWillAppear: function() {
},
componentDidAppear: function() {
},
});
那么,场景一该如何写,你是不是已经有了答案? 这时我要抛出一个问题,为什么有enter类,还要有个enter-active类?类似地,为什么有个componentWillEnter还要有DidEnter呢?它是为了解决什么场景?细想下与传统CSS方案相比,它的高明之处。
采用react官网介绍的解决方案基本可以满足我们的需求,但不够丰盛。 我找到2个react-animate的解决方案,一个是facebook带来的react-motion,一个是ant封装的rc-animate。
我在cat-message中试验了react-motion,但cat项目组还没有最终决定。对比三者:官网,react-motion,rc-animate,初步的“偏爱”是因为react-motion在github上的star更多(2666)。 初步总结react-motion的特点, API更灵活,API略难懂但是经过学习完全可以掌握。