Closed ninjz closed 4 years ago
I think I experienced something similar on Android. After stopping clock I see that frameTime progresses. Even though if was reset to 0.
@likern Did you come into any workaround for this? I've verified just now that starting and stopping the clock in the parent causes no update to the clock state in the child. I placed debug statements within the cond
to see if the negated state was being executed when the clock stopped and it isn't.
I'm not sure if it's related by that is used child component.
I experienced that from my main component - when I stopped clock I expected timing
function should not update position
and return old one. And when I resume clock it should update from position when it was initially stopped.
My use case - to be able to interrupt animation if uses presses on animated screen. And resume on finger release.
I don't know is it a bug or working as expected. But frameTime is a wall clock
- it is updated even on stopped clock. I think it's responsible for (hidden) animation.
My solution was - at animation freeze I save both frameTime
and position
(in other variables created in useMemoOne) and set them back to state's frameTime and position when I restore animation.
Also I set time to 0 when restore animation. And it's working!
hmm, I think in your case just setting time to 0 should be enough to handle that case, as looking into the implementation here setting time to zero would preserve the last frameTime. Right now it's looking like:
return block([
cond(
not(clockRunning(clock)),
[
set(state.time, 0), // <---- Not being called when clock is stopped
],
timing(clock, state, config) // <---- Called when clock is running
),
state.position
]);
the truthy condition in the above code block is not executed when the clock has stopped running. My hunch is that this is a bug, or I am just going against how the Clock is supposed to be used.
I haven't dig in the internal implementation details. But in my opinion there is definitely something broken in implementation. I can use PanGesture or just animation. But as soon as I try to run animation after PanGesture - things become messed up. I see dragging when I use timing even if I don't use it's state at all. I calculate position based on PanGesture and if I add timing (without using it's calculation) position unexpectedly changed so I see draggin and twitching.
It's fifth day I try to make this working.
This is intended (but unexpected) behavior. Stopped clocks don't keep their value frozen but still update. Stopping a clock means that nodes that depend on that clock won't be updated.
Clocks work internally by synchronizing to singleton main clock.
The easiest way to work around that is to keep the clock's value in some other Animated.Value
.
@jakub-gonet @likern
facing a similar issue I try to pause the clock
when the app is going to the background
state and resume the clock
when the app is coming to the active
state.
clock config
const runTiming = (clock,timing) => {
const state = {
finished : new Value(0),
position : new Value(0),
frameTime : new Value(0),
time : new Value(0)
};
const config = {
toValue : new Value(1),
duration :timing ,
easing : Easing.in(Easing.ease)
};
return block([
cond(not(clockRunning(clock)), set(state.time, 0), timing(clock, state, config)),
cond(eq(state.finished, 1), stopClock(clock)),
state.position
]);
}
SpecialTestTimer.js
const SpecialTestTimer = ({ preparationTime, appState,timing }) => {
const [ isCompleted, setIsCompleted ] = useState(false);
const clock = useClock();
const progress = useValue(0);
const [ play, setPlay ] = useState(true);
const isPlaying = useValue(0);
useEffect(
() => {
if (appState == 'active') setPlay(true);
else setPlay(false);
},
[ appState ]
);
useCode(() => set(isPlaying, play ? 1 : 0), [ play ]);
useCode(
() => [
cond(and(isPlaying, not(clockRunning(clock))), startClock(clock)),
cond(and(not(isPlaying), clockRunning(clock)), stopClock(clock)),
set(progress, runTiming(clock,timing))
],
[]
);
...
}
I'm experiencing this issue where passing an instance of a Clock which is started->stopped->resumed in the parent component, is not being properly resumed in the timing function in the child. Whereas if I was to place the logic of starting and stopping the clock within the child component the Clock is able to pause and resume from the last played position.
To clarify, by pausing and resuming; I mean that once resuming, I expect the position to resume from the last position. In the code below, I see that the position is ahead once I resume as if the clock was not being properly stopped.
The use case I have for this is to create a master timer which is counting down a total duration using a Timing function in the parent on the same clock. And within the child component, I want to be able to run another Timing function with the same clock to keep track of another duration. Is this the correct approach or should I be creating to separate clocks to be managing two timers?
Any help on this would be greatly appreciated.
Thanks.
(Irrelevant parts of the code have been omitted.)