React中常见的动画实现的几种方式(2)

在示例中,我们在 increasedecrease 函数中构建线性过渡函数 animationrequestAnimationFrame 在浏览器每次重绘前执行会执行过渡函数,计算当前进度条 width 属性并更新该 state ,使得进度条重新渲染。该示例的效果如下所示:

这种实现方式在使用 requestAnimationFrame 时性能不错,完全使用纯 js 实现,不依赖于 css,使用定时器时可能出现掉帧卡顿现象。此外,还需要开发者根据速度函数自己计算状态,比较复杂。

二、基于 css3 的简单动画

当 css3 中的 animationtransition 出现和普及后,我们可以轻松地利用 css 实现元素样式的变化,而不用通过人为计算实时样式。

示例

我们仍以上面的进度条为例,使用 css3 实现进度条动态效果,代码如下所示:

import React, { Component } from 'react';

export default class Progress extends Component { 
  constructor(props) {
    super(props);
    this.state = {
      percent: 10
    };
  }

  increase = () => {
    const percent = this.state.percent + 10;
    this.setState({
      percent: percent > 100 ? 100 : percent,
    })
  }

  decrease = () => {
    const percent = this.state.percent - 10;
    this.setState({
      percent: percent < 0 ? 0 : percent,
    })
  }

  render() {
    // 同上例, 省略
    ....
  }
}
.progress-inner {
 transition: width 400ms cubic-bezier(0.08, 0.82, 0.17, 1);
 // 其他样式同上,省略
 ...
}

在示例中, increasedecrease 函数中不再计算 width ,而是直接设置增减后的宽度。需要注意的是,在 css 样式中设置了 transition 属性,该属性在其指定的 transition-property 发生变化时自动实现样式的动态变化效果,并且可以设置不同的速度效果的速度曲线。该示例的效果如下图所示,可以发现,与上一个例子不同的是,右侧的进度数据是直接变化为目标数字,没有具体的变化过程,而进度条的动态效果因为不再是线性变化,效果更为生动。

基于 css3 的实现方式具有较高的性能,代码量少,但是只能依赖于 css 效果,对于复杂动画也很难实现。此外,通过修改 state 实现动画效果,只能作用于已经存在于 DOM 树中的节点。如果想用这种方式为组件添加入场和离场动画,需要维持至少两个 state 来实现入场和离场动画,其中一个