my use-case is to call a setState after runTiming or runSpring was done springing the value.
here is my code
function runSpring({ translateY, velocityY, state: _state }) {
const clock = new Clock();
const state = {
finished: new Value(0),
velocity: new Value(0),
position: new Value(0),
time: new Value(0)
};
const config = {
stiffness: new Value(10),
mass: new Value(1),
damping: new Value(10),
overshootClamping: false,
restSpeedThreshold: 0.001,
restDisplacementThreshold: 0.001
};
const configB = SpringUtils.makeConfigFromBouncinessAndSpeed({
...SpringUtils.makeDefaultConfig(),
bounciness: 10,
speed: 2
});
const configC = SpringUtils.makeConfigFromOrigamiTensionAndFriction({
...SpringUtils.makeDefaultConfig(),
tension: 100,
friction: new Value(40)
});
// startClock(clock);
return block([
cond(lessOrEq(translateY, 0), [
cond(
lessOrEq(velocityY, -300),
[
startClock(clock),
spring(clock, state, { ...config, toValue: -DeviceHeight })
],
[
cond(
eq(_state, State.END),
[startClock(clock), spring(clock, state, config)],
[
set(state.position, translateY)
// debug("clock 2 happened", eq(_state, State.ACTIVE))
]
)
]
)
]),
state.position
]);
}
port default class ExampleTab extends React.Component {
constructor(props) {
super(props);
this.state = {
currentItemIndex: 0
};
this._translateY = new Value(0);
this._state = new Value(State.UNDETERMINED);
this._velocityY = new Value(0);
this.currentCardVelocity = new Value(0);
this.translateY = runSpring({
translateY: this._translateY,
velocityY: this._velocityY,
state: this._state
});
}
render(){
return (
<PanGestureHandler
key={pIndex}
{...gestureEvent}
// onHandlerStateChange={this.handleGState}
enabled={indexDistance === 0}
>
<Animated.View
style={{
flex: 1,
shadowOffset: { height: 3 },
elevation: 3,
// borderWidth: 0.5,
borderColor: "black",
borderRadius: 25,
shadowColor: "black",
shadowOpacity: 0.5,
justifyContent: "flex-end",
transform: [
{
translateY:
indexDistance === 0
? this.translateY
: isPrevCard
? prevCardTranslateY
: translateY
}
],
// opacity: animatedOpacity,
marginHorizontal: multiply(indexDistance, secondCardGrowth),
...StyleSheet.absoluteFillObject
}}
>
</Animed.View>
</PanGestureHandler>
) }
}
}
You can do it like below.
Using conditionals with the finished state at the end of the block and the call function to do a callback from js side:
[ ...previous block animated events...,
cond(state.finished,
call([...your params here], (...your params) => {...function })
)
]
how to check for state.finished ? its a value(0)
You are passing the state object as param in spring function. Technically these values will be updated while the clock is running.
i tried ,. but that callback is getting called continuously and endlessly
return block([
cond(lessOrEq(translateY, 0), [
cond(
lessOrEq(velocityY, -3300),
[
startClock(clock),
spring(clock, state, { ...config, toValue: -DeviceHeight })
],
[
cond(
eq(_state, State.END),
[
startClock(clock),
spring(clock, state, { ...config, toValue: 0 })
// stopClock(clock)
],
[
set(state.position, translateY)
// debug("clock 2 happened", eq(_state, State.ACTIVE))
]
)
]
)
]),
// cond(state.finished, [stopClock(clock), call([state.finished], callback)]),
state.position
]);
tell me my mistake
Hmmmm, can you create a sample in snack? Because visually I didn't find any errors in your code.
i cant. this is a commercial product.
but i noticed its not mentioned to call startClock(clock) manually. But for me , it is not animating value if i didn't started it manually. do you think it the cause ? @brunocrpontes
Not exactly @vamshi9666, clocks are useful when the imperative animations can't cover the behaviour what you're looking for. Anyway I think it's just a logic mistake, but without an example or a description is hard to figure out.
At the end, I'm 100% sure which my first answer solve you issue question about the callback, because the example in read-me show a similar situation (call something when the animation is done) but instead a call it's a debug function.
```.ts
...previous code
timing(clock, state, config),
// if the animation is over we stop the clock
cond(state.finished, debug('stop clock', stopClock(clock))),
// we made the block return the updated position
state.position,
```
Maybe it's because you need to reset the state values if your clock isn't running? These nodes are continually evaluated, as far as I understand.
return block([
clockRunning(clock),
[
// if the clock is already running we update the toValue, in case a new dest has been passed in
set(config.toValue, toValue)
],
[
// if the clock isn't running we reset all the animation params and start the clock
set(state.finished, 0),
set(state.time, 0),
set(state.frameTime, 0),
set(config.toValue, toValue),
startClock(clock)
]
),
timing(clock, state, config),
cond(state.finished, [stopClock(clock), /* do finished stuff */]),
state.position
]);
So I'm not the only one...
Hi @vamshi9666,
your first question was answered by @brunocrpontes.
Your second question is a bit unclear though - could you provide a minimal reproducible example on snack with a detailed explanation of what you want to achieve? It's hard to answer that directly judging by code.
Thanks for understanding and have a nice day!
Hi @jakub-gonet, I'm facing the second problem, how can I make a callback to be called only once after a condition is met. For example:
cond(eq(state, State.ACTIVE), [call([someAnimValue], handlefFinished)])
Because as I saw in the the document, it said If one of the nodes from argsNodes array updates, callback will be called, but I don't want the callback to be called again and again if my someAnimValue is changed, how can I do it?
Sorry for the late reply,
you can use some variable to 'block' it.
Something like:
Cond(and(state, flag), action, set(flag, 1))
Maybe it's because you need to reset the state values if your clock isn't running? These nodes are continually evaluated, as far as I understand.
return block([ clockRunning(clock), [ // if the clock is already running we update the toValue, in case a new dest has been passed in set(config.toValue, toValue) ], [ // if the clock isn't running we reset all the animation params and start the clock set(state.finished, 0), set(state.time, 0), set(state.frameTime, 0), set(config.toValue, toValue), startClock(clock) ] ), timing(clock, state, config), cond(state.finished, [stopClock(clock), /* do finished stuff */]), state.position ]);
This is only happening in React Hook, but not class component. setState in class component works ok
To anyone it might help.
return block([
cond(not(clockRunning(clock)), [
set(state.finished, 0),
set(state.time, 0),
set(state.frameTime, 0),
set(state.position, from),
set(config.toValue, to),
startClock(clock),
]),
timing(clock, state, config),
cond(state.finished, debug('stop clock', stopClock(clock))),
cond(
state.finished,
call([state.position], (value) => {
if (typeof callback === 'function') callback(value[0]);
}),
),
state.position,
]);
stopping the clock then calling the callback worked.
it gets called once after the animation ends.
Note: if you do not stop the clock the callback will get called continuously every time the duration you set elapses. e.g every 500 ms.
Most helpful comment
You can do it like below.
Using conditionals with the finished state at the end of the block and the call function to do a callback from js side: