React总结篇之十_动画

  • 在网页中动画的实现方式
  • React提供的动画辅助工具ReactCSSTransitionGroup
  • React-Motion动画库

一、动画的实现方式
在网页中,实现动画无外乎两种方式:

  • CSS3方式,也就是利用浏览器对CSS3原生支持实现动画;
  • 脚本方式,通过间隔一段时间用JavaScript来修改页面元素样式来实现动画。
  1. CSS3方式
    CSS3的方式下,开发者一般在CSS中定义一些包含CSS3transition语法的规则。在某些特定情况下,让这些规则发生作用,于是浏览器会将这些规则应用于指定的DOM元素上,产生动画的效果。这种方式效率比脚本方式高,因为浏览器原生支持,省去了JavaScript的解释执行负担,有的浏览器甚至可以充分利用CPU加速的优势,进一步增强动画渲染的性能。
    不过CSS3也有不少缺点:
    首先,CSS3transition对一个动画规则的定义是基于时间和速度曲线的规则。就是CSS3的动画过程要描述成“在什么时间范围内,以什么样的运动节奏完成动画”,这可能不利于动画的流畅,因为动画是可能被中途打断的。
    因为CSS3transition总是一闪而过,捕捉不到中间状态,只能一遍一遍用肉眼去检查动画效果,这给开发者带来了很大的痛苦。

  2. 脚本方式
    相对于CSS3方式,脚本方式最大的好处就是更强的灵活性,开发者可以任意控制动画的时间长度,也可以控制每个时间点上动画渲染的样式,可以更容易做出丰富的动画效果。
    脚本方式的缺点也很明显,动画过程通过JavaScript实现,不是浏览器原生支持,消耗的计算资源更多。

二、 ReactCSSTransition规则
Transition并不能代替CSS,相反,它离不开CSS,其扮演的角色是让React组件在生命周期的特定阶段使用不同的CSS规则,而连接React组件和CSS需要遵守一些规则。

  1. 类名规则
    配合TransitionGroup中的transitionName属性,对应CSS规则中类名遵从统一的规则。类名由-符号把几个单词连接起来,除了transitionName的值,还可以有这几个单词:enter代表“装载”开始时的状态,leave代表“卸载”开始时的状态,active代表动画结束时的状态。
    假设transitionName为sample,那么定制相关React组件的类名就是:
    • sample-enter
    • sample-enter-active
    • sample-leave
    • sample-leave-active
      其中active后缀类名的作用比较特殊,因为用CSS3的transition功能实现动画,必须定义“开始状态”和“结束状态”,只有存在这两个状态,CSS3才知道如何将元素属性从“开始状态”在指定的时间按照指定的速度曲线转换为“结束状态”,这两个状态必须定义在两个不同的CSS类中,否则CSS3无法区分。
  2. 动画时间长度
    使用TransitionGroup,动画的持续时间在两个地方都要指定,第一个是在Transition-Group中以Timeout为结尾的属性,第二个地方是在CSS文件中transition-duration规则。
  3. 装载时机
    TransitionGroup要发挥作用,必须自身已经完成装载了。因为Transition也只是一个React组件,功能只有在被装载之后才能发挥。
  4. 首次装载
    在Todo应用中,TransitionGroup自身被装载的时候,可能已经包含了若干个TodoItem组件实例,但这些TodoItem组件虽然经历了装载过程,却没有动画效果,只有在TransitionGroup被装载之后新加入的TodoItem组件才有动画效果。如果想让这些子组件也有动画效果,那就要使用appear过程,appear代表的就是随TransitionGroup一起“出现”的过程。

三、React-Motion动画库
React-Motion使用的是脚本方式。
react-motion中大量的使用了“以函数为子组件”的模式,react-motion提供的组件,都预期接受一个函数作为子组件。举例如下:
React总结篇之十_动画
Motion组件的defaultStyle属性指定了一个初始值,style属性指定了目标值,期间不断调用作为子组件的函数,完成动画过程。
很显然,motion并不直接参与动画的绘制,它只是提供参数。具体的绘制过程,由作为子组件的绘制函数来完成,很显然这种“以函数为子组件”的模式带来了很大的灵活度。