我是react-native-reanimated
的新手,正努力将其工作原理包裹住。下面的代码在屏幕中间渲染一个方框。在初始渲染时,该框会向右平移4秒钟,然后将其位置重置到屏幕中间。
... imports omitted for brevity
export default class App extends React.Component {
state = {
clock: new Clock(),
translation: new Value(0),
};
onPress = () => {
startClock(this.state.clock);
};
getTranslation = (clock, translation) => {
const state = {
finished: new Value(0),
position: translation,
time: new Value(0),
frameTime: new Value(0),
};
const config = {
duration: 4000,
toValue: new Value(300),
easing: Easing.inOut(Easing.ease),
};
return block([
cond(clockRunning(clock), 0, [
set(state.finished, 0),
set(state.position, 0),
set(state.time, 0),
set(state.frameTime, 0),
startClock(clock),
]),
timing(clock, state, config),
cond(state.finished, set(state.position, 0)),
state.position,
]);
};
render() {
const translation = this.getTranslation(
this.state.clock,
this.state.translation
);
return (
<View style={styles.container}>
<TouchableOpacity onPress={this.onPress}>
<Animated.View
style={{
transform: [
{
translateX: translation,
},
],
width: 100,
height: 100,
backgroundColor: "tomato",
}}
/>
</TouchableOpacity>
</View>
);
}
}
我的问题是:
1)为什么框仅在初始渲染时平移到右侧? 是什么阻止动画重复?
2)onPress处理程序不会重新启动动画。为什么?
答案 0 :(得分:0)
我也在学习恢复本地化的反应,但是我会尽力回答您的问题。如果有人要编辑答案,请自由编辑。
- 为什么框仅在初始渲染时平移到右侧?是什么阻止动画重复?
在安装组件时,translateX
的值为0,它将位于屏幕的中心(因为您已经说过,styles.container
的样式可能以其子组件为中心)。
并且由于您要从render方法中的getTranslation
函数请求转换,因此当组件首次渲染时,将调用getTranslation
函数并评估一个节点块:
block
列表中的第一个节点,即cond
块。它检查时钟是否正在运行。
timing
状态和配置。请记住,state.position
设置为0,并且config.toValue
也已经设置为300。然后开始计时。state.position
设置为0,并将config.toValue
设置为300,因此state.position
被更新为1(取决于config.duration
)。finished
值是否为1。
position
等于配置值toValue
时,timing
函数将更新finished
的值到1。position
值将再次设置为0。这意味着该位置会重置为其原始位置。在最后一个节点上,状态的position
返回到render方法的translation
常量进行转换。
由于时钟开始并且动画尚未结束,因此节点块一次又一次运行。在下一帧中,state.position
的值将为2,随后为3,依此类推,直到state.position
等于300(config.toValue
)。因此,该框将从屏幕的中心移到右侧。但是,如果您将config.toValue
设置为-300,则该框将从屏幕的中心移到屏幕的左侧。
最后,当动画结束时,该块的第3个节点等于true,并且state.position
再次为0(在屏幕中央)。
并且由于您尚未停止时钟(可以使用stopClock(clock)
完成),因此检查clockRunning(clock)
的第一个节点始终为true。另外,要重复播放动画,您必须在动画完成后重置所有timing
状态和配置。
因此,您必须更改节点块:
return block([
cond(
clockRunning(clock),
[
debug('clock is running', clock)
],
[
debug('clock is NOT running', clock),
startClock(clock),
]
),
timing(clock, state, config),
cond(
state.finished,
[
stopClock(clock),
set(state.finished, 0),
set(state.position, 0),
set(state.time, 0),
set(state.frameTime, 0),
startClock(clock),
]
),
state.position,
]);
- onPress处理程序不会重新启动动画。为什么?
因为时钟没有停止。也因为状态和配置未重置。因此,要在按下动画时开始动画,可以用许多不同的方法来完成。我将向您展示如何通过一种方式进行操作,这种方式可能会让您对react-native-reanimated
以及react-native-gesture-handler
有了更多的了解,可以与纯本地动画一起使用,而不必过桥。 / p>
const getTranslation = ({clock, gestureState, translation}) => {
const state = {
finished: new Value(0),
position: translation,
time: new Value(0),
frameTime: new Value(0),
};
const config = {
duration: 2000,
toValue: new Value(150),
easing: Easing.inOut(Easing.ease),
};
return block([
cond(
clockRunning(clock),
[
debug('clock is running', clock)
],
[
debug('clock is NOT running', clock),
set(state.finished, 0),
set(state.position, 0),
set(state.time, 0),
set(state.frameTime, 0),
startClock(clock),
]
),
timing(clock, state, config),
cond(
state.finished,
stopClock(clock)
),
state.position
])
};
export default class App extends React.Component {
gestureState = new Value(-1)
clock = new Clock()
translation = cond(
eq(this.gestureState, State.ACTIVE), // when you start drag, the state will be ACTIVE
[
debug('active', this.gestureState, State.ACTIVE),
getTranslation({clock: this.clock, translation: new Value(0)})
],
[
debug('not active', this.gestureState, State.ACTIVE)
],
)
onStateChange = event([
{
nativeEvent: {
state: this.gestureState
}
}
])
render() {
return (
<View style={styles.container}>
<PanGestureHandler
onGestureChange={this.onStateChange}
onHandlerStateChange={this.onStateChange}>
<Animated.View style={[
styles.box,
{
transform: [{
translateX: this.translation
}]
}
]}/>
</PanGestureHandler>
</View>
)
}
}