先解释一个非常简单的示例,然后由这个示例引申到useSpring
的使用及配置。
import React from 'react';
import { useSpring, animated } from 'react-spring';
const App = () => {
const { number } = useSpring({ number: 0, from: { number: 1 } });
return <animated.div>{number.interpolate(n => n.toFixed(2))}</animated.div>;
};
export default App;
如上面的代码,会看到的动画是,数字由1变为0,且变化过程中,数字一直保持2为小数。
useSpring配合animated
使用,可以使元素从一个状态变为另外一个状态,如上面所示,初始状态 number为1,最终状态为number为0,元素进行了从初始状态到最终状态的变化,而这种变化是通过动画的形式展现的。
useSpring
是一个React Hook。它定义了,动画的初始状态、最终状态以及一些变化参数。先看基本的,useSpring
若接受一个对象为参数(实例中就是以对象为参数),则这个对象可以包含以下属性:
from
,表示初始状态
to
,表示最终状态。需要注意的是,所有未在react-spring
API 中指定的参数,都会被视为 to
终止状态的数据。比如上面示例中useSpring({ number: 0, from: { number: 1 } })
,number并不是API指定的配置参数,所以number:0
是to
的数据之一,也就是说,它等价于useSpring({ to: { number: 0 }, from: { number: 1 } });
delay
,动画等待时间,如设置为1000,则动画会在等待1s后才执行
immediate
,值为一个布尔值或者一个返回布尔值的函数,若布尔值为true或函数执行结果为true,则会从开始状态直接变为最终状态,而不执行动画
reverse
,对调动画的最终状态和初始状态,只有当设置了reset
为true时才有意义
config
,动画配置。
duration
、precision
、easing
等参数。如上示例中,变为如下形式,则数字从1变为0会在3s钟内进行,动画会维持3s。全部可配置项可以参见react-spring官网common-api的configconst { number } = useSpring({ to: { number: 0 }, from: { number: 1 }, config: { duration: 3000 } });
default
、gentle
等,可以使用以下方式进行引用import { ..., config } from 'react-spring'
useSpring({ ..., config: config.default })
useSpring({ ..., config: config.gentle })
onStart
,当动画开始时,执行这个函数
onFrame
,动画的每帧播放时调用,会传入此时的动画值,动画值见下面useSpring
的返回值解释
useSpring
的返回值是一个对象,这个对象的属性,是useSpring
参数中的状态值。对象中的各状态值会随着动画的进行而变化。最开始的时候,此状态值是初始状态值;动画开始后,状态值变为动画状态对应的值;最终在动画结束时,此状态值变为最终状态。
比如在上述示例中,采用了结构赋值,返回的实际值是一个 {number:AnimatedValue}
,表示返回的是一个对象,这个对象有一个number属性,而number的值是一个对象,这个对象是AnimatedValue
类型,它有一个value
属性,其值为0。之后动画进行时,这个value值会随着动画状态变更,最终变为最终状态中的1
const { number } = useSpring({ number: 0, from: { number: 1 } });
import React from 'react';
import { useSpring, animated } from 'react-spring';
const App = () => {
const [{ number }, set, stop] = useSpring(() => ({ number: 1, from: { number: 0 } }));
function handleClick () {
if (number.value === 1) {
set({ number: 0 });
} else if (number.value === 0) {
set({ number: 1 });
}
}
return (
<div>
<animated.div>
{number.interpolate(n => n.toFixed(2))}
</animated.div>
<button onClick={handleClick}>reverse</button>
</div>
);
};
export default App;
上面代码实现的效果是:页面加载后,数字0会使用动画变为1,此时点击reverse按钮,数字又会由1以动画形式变为0,再次点击reverse,则又会变为1。
如上面代码所示:
useSpring
可以接受一个函数作为参数,这个函数的的返回值是一个对象,此对象是上面已经讲述过的那个,可以有from、to等参数useSpring
接受函数为参数时,它的返回值是一个数组,上面采用了解构赋值的方式,数组中包含三个值,第一个返回值和上面useSpring
接受对象时的返回值相同,第二个返回值是一个set函数,第三个返回值是一个stop函数setState
很相似,可以将动画状态至为某个指定状态(这个指定状态就是调用set函数时的入参),调用set函数后,react-spring会按照useSpring
中指定的动画配置,将元素以动画的形式变为指定状态。interpolate的作用是,设定动画的呈现:
n=>n.toFixed(2)
,则,每个number值在呈现的时候,都只会取两位小数number.interpolate([0,0.5,1],[0,1.9.2])
,它表示的是,动画执行时,0时刻,应该输出0;中间时刻点应该输出1.9;到最终动画中点,应该是2。此时第二个数组的输出,也就是对应时刻,动画应该在的状态。range
、output
、extrapolate
等属性interpolate也可以串联使用,比如
number
.interpolate([0, 0.5, 1], [2, 1.9, 0])
.interpolate(n => n.toFixed(2))
此时由.interpolate([0, 0.5, 1], [2, 1.9, 0])
输出的值会作为.interpolate(n => n.toFixed(2))
的输入,经过取两位小数再进行输出。
useSpring的to属性可以接受一个异步函数作为参数,在此异步函数中可以执行异步动画,比如下面的例子中,会等到接口请求返回才执行动画,每次next的时候回next出一个动画状态,然后会执行动画,将元素状态置为这个状态
import React from 'react';
import { useSpring, animated } from 'react-spring';
import fetch from 'cross-fetch';
const App = () => {
const { number } = useSpring({
to: async (next, cancel) => {
const res = await fetch('https://www.reddit.com/r/reactjs.json');
await next({ number: 1 });
await next({ number: 0 });
},
from: { number: 0 }
});
return <animated.div>{number.interpolate(n => n.toFixed(2))}</animated.div>;
};
export default App;
to 可以被指定为状态组成的数组,此时会从左往右,执行动画依次进行状态变更。如下面,会先变为1,然后再变为2
const App = () => {
const { number } = useSpring({
to: [{ number: 1 }, { number: 2 }],
from: { number: 0 }
});
return <animated.div>{number.interpolate(n => n.toFixed(2))}</animated.div>;
};