概念
定义动画的一个标量值。
// 用法如下
// 声明一个初始值为 0 的标量值
const v = new Animated.Value(0);
使用步骤
- 创建一个 Animated.Value 对象
- 把声明的值设置到动画组件(Animated.View)的一个或多个属性上
- 执行 Animated.timing() 等方法设置动画的执行效果
- 最后 Animated.start() 启动动画执行
一个简单的例子
import React from 'react'
import { Button, Animated } from 'react-native'
function Main() {
const v = new Animated.Value(0)
const start = () => {
Animated.timing(v, {
toValue: Math.random() * 500
}).start()
}
return (
<Animated.View
style={{
width: 100,
height: 100,
backgroundColor: '#f00',
transform: [{ translateY: v }]
}}
>
<Button title="start" onPress={start} />
</Animated.View>
)
}
export default Main
其它相关的一些方法很好理解,比如执行动画的相关方法 start stop reset,设置动画效果的方法 timing spring decay。但有两个比较复杂或者说比较难理解的方法 interpolate Animated.event。
Animated.event
它是用于处理手势或其它事件的,用于把事件的值直接映射到动画值上。
Takes an array of mappings and extracts values from each arg accordingly, then calls setValue on the mapped outputs.
它的方法定义如下,接收两个参数,一个数组,一个可选的配置。难理解的有两点,一个是第一个参数的,一个是如何绑定到手势等事件上。
// define
static event(argMapping, config?)
Animated.event(
[], // 依次提取值设置到最里面的 Animated.Value 上
{
listener: () => {}, // 异步的监听回调
useNativeDriver: false, // 启用原生动画
}
)
第一个参数
依次提取值设置到最里面的 Animated.Value 上。下面的例子,等同于这样的赋值操作
v = event.nativeEvent.contentOffset.y
const v = Animated.Value(0)
Animated.event(
[
{
nativeEvent: {
contentOffset: { y: v }
}
}
]
)
绑定到事件上
注意需要直接把 Animated.event() 的返回值直接绑定到事件上
import React from 'react'
import { View, Animated, ScrollView } from 'react-native'
function Main() {
const v = new Animated.Value(0)
const onScroll = Animated.event(
[{
nativeEvent: {
contentOffset: {
y: v,
}
}
}], {
listener: (e) => {
console.log(e.nativeEvent.contentOffset)
}
}
)
return (
<View style={{flexDirection: 'row'}}>
<Animated.View style={{ flex: 1, height: 100, backgroundColor: '#00f', transform: [{translateY: v}]}} />
<ScrollView
style={{
flex: 1,
backgroundColor: '#61dafb',
}}
onScroll={onScroll}
>
<View style={{height: 1600}} />
</ScrollView>
</View>
)
}
export default Main
interpolate
Interpolates the value before updating the property, e.g. mapping 0-1 to 0-10.
简单说它就是根据 Animated.Value 的值,如果它的值在 inputRange 范围内则按比例计算出一个在 outputRange 范围内的值返回,超过 inputRange 的值忽略处理。
比如下面的定义,假如当前 v._value=9 则对应的 ov=90。
注意这里的 ov 需要绑定到 Animated.View 的属性上。
const v = Animated.Value(0)
const ov = v.interpolate({
inputRange: [0, 10],
outputRange:[0, 100],
extrapolate: 'clamp'
})
一个完整的例子
import React from 'react'
import { View, Animated, ScrollView } from 'react-native'
function Main() {
const v = new Animated.Value(0)
const onScroll = Animated.event(
[{
nativeEvent: {
contentOffset: {
y: v,
}
}
}], {
listener: (e) => {
console.log(e.nativeEvent.contentOffset)
}
}
)
const ov = v.interpolate({
inputRange: [0, 100],
outputRange: [0, -100],
extrapolate: 'clamp'
})
return (
<View style={{flexDirection: 'row', alignItems: 'flex-end'}}>
<Animated.View style={{ flex: 1, height: 100, backgroundColor: '#00f', transform: [{translateY: ov}]}} />
<ScrollView
style={{
flex: 1,
backgroundColor: '#61dafb',
}}
onScroll={onScroll}
>
<View style={{height: 1600}} />
</ScrollView>
</View>
)
}
export default Main
网友评论