React中常见的动画实现的几种方式(2)
在示例中,我们在 increase
和 decrease
函数中构建线性过渡函数 animation
, requestAnimationFrame
在浏览器每次重绘前执行会执行过渡函数,计算当前进度条 width
属性并更新该 state
,使得进度条重新渲染。该示例的效果如下所示:
这种实现方式在使用 requestAnimationFrame
时性能不错,完全使用纯 js 实现,不依赖于 css,使用定时器时可能出现掉帧卡顿现象。此外,还需要开发者根据速度函数自己计算状态,比较复杂。
二、基于 css3 的简单动画
当 css3 中的 animation
和 transition
出现和普及后,我们可以轻松地利用 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); // 其他样式同上,省略 ... }
在示例中, increase
和 decrease
函数中不再计算 width
,而是直接设置增减后的宽度。需要注意的是,在 css 样式中设置了 transition
属性,该属性在其指定的 transition-property
发生变化时自动实现样式的动态变化效果,并且可以设置不同的速度效果的速度曲线。该示例的效果如下图所示,可以发现,与上一个例子不同的是,右侧的进度数据是直接变化为目标数字,没有具体的变化过程,而进度条的动态效果因为不再是线性变化,效果更为生动。
基于 css3 的实现方式具有较高的性能,代码量少,但是只能依赖于 css 效果,对于复杂动画也很难实现。此外,通过修改 state
实现动画效果,只能作用于已经存在于 DOM 树中的节点。如果想用这种方式为组件添加入场和离场动画,需要维持至少两个 state
来实现入场和离场动画,其中一个