Stop a Animated.loop with native driver - so it triggers the start callback - react-native

I am running a loop like this:
const anim = new Animated.Value(0);
const res = Animated.loop(
Animated.timing(anim, {
duration: 2000,
toValue: 1,
easing:Easing.inOut(Easing.linear),
useNativeDriver: true,
isInteraction: false
})
);
res.start(e => console.log('anim stopped, e:'));
setTimeout(()=>res.stop(), 5000); // does not trigger callback
// setTimeout(()=>anim.stopAnimation(), 5000); // does not trigger callback
The animation runs, and loops properly. (animated value goes back to 0 at start of each loop).
And the animation stops, if i do either res.stop() or anim.stopAnimation(). But the start callback never triggers. I'm worried that something is still running and I might have a memory leak. Can you please advise on how to properly stop a native driver loop?

Although I couldn't find it in the documentation, there is an optional onComplete key available on the AnimationConfig type (I found it at the top of Animation.js in the repo). The log will now appear when your animation is stopped by adding the callback inside of your configuration:
const res = Animated.loop(
Animated.timing(anim, {
duration: 2000,
toValue: 1,
easing:Easing.inOut(Easing.linear),
useNativeDriver: true,
isInteraction: false,
onComplete: (e) => console.log('anim stopped, e:') // New config option
})
);
There's no guarantee that this won't be a breaking change in the future, but it seems like a pretty safe key name to stick with, so I don't see them refactoring that anytime soon.
As for your concern about the memory leak, the Animated.loop calls the stop() method of the child animation, so you should have no concerns there.

Related

Stopping Animated timing in react native

I have created a number ticker like odometer in my react native application. But when I click on the button to start the animation it just goes on. I want to stop the animation after like 5 seconds. Here's the part where I think some modification should be done:
componentDidUpdate(prevProps, prevState) {
if (this.props.value !== prevProps.value) {
Animated.timing(this.animation, {
toValue: getPosition(this.props.value, this.props.height),
duration: 500,
useNativeDriver: true,
}).start(function onComplete() {
Animated.timing(this.animation).stop();
});
}
}
Running this throws an error like Cannot read property 'stopAnimation' of undefined.If I remove the onComplete function it just goes on. So,how can I stop this after 5 seconds?
You are using the animation completion callback. It means you are trying to stop something that already ended.
Try
componentDidUpdate(prevProps, prevState) {
if (this.props.value !== prevProps.value) {
Animated.timing(this.animation, {
toValue: getPosition(this.props.value, this.props.height),
duration: 500,
useNativeDriver: true,
}).start();
Animated.timing(this.animation).stop()
}
}
You will stop the animation right after starting it.
The simplest way to stop any kind of animation by calling setValue() method and assign a value.
In your case:
this.animation.setValue(0);
For more details https://reactnative.dev/docs/animatedvaluexy#setvalue
You can use this.animation.stopAnimation();

react-native: Animate position of Animated.View during onPanMove

I have set up an animation and want to animate a View, so when the user touch moves the view follows on the y axis.
I have tried to set this up with Animated.event but it doesn't work. Can somebody please explain how Animated.event works in a panResponder?
This is what I have:
const onPanMove = (evt: GestureResponderEvent, state: PanResponderGestureState) => {
Animated.event([null, {dy: new Animated.Value(state.dy)}], {useNativeDriver: true});
};
But nothing happens. I also googled a lot, but didn't find any good documentation on this.
When I replace the event with timing it works, but it's super laggy since it always waits for the touchmove to pause.
Animated.timing(
this.state.position,
{
toValue: startY - state.dy,
duration: 0,
//easing: this.props.easing,
useNativeDriver: true
}
).start();

Backgroungeolocation engage ionic3

I'm using mauron85 Backgroundgeolocation plugin for my ionic 3 application.
It works, the only problem is the timing when it engage.
The problem is even if I subscribe and start the plugin, it engage only after a couple of minutes.
Namely it returns the position in the moment that I start it, but before engaging and actively tracking it takes some time.
Also sometime when I put the app in background it does not start recording.
That is the code I used:
import { BackgroundGeolocation, BackgroundGeolocationConfig, BackgroundGeolocationResponse } from '#ionic-native/background-geolocation';
Then the consifugration and start:
let config: BackgroundGeolocationConfig = {
locationProvider: 0,
desiredAccuracy: 10,
stationaryRadius: 1,
distanceFilter: 1,
activitiesInterval: 100,
interval: 1000,
notificationTitle: 'TiCaccio is tracking you',
notificationText: 'you know it, right?'
// debug: true
};
this.backgroundGeolocation.configure(config).subscribe((location: BackgroundGeolocationResponse) => {
console.log("Background location", location);
this.lat = location.latitude;
this.lng = location.longitude;
});
this.backgroundGeolocation.start();
Now the problem is in fact that sometimes it engage, sometimes not. And even when it engage it just do that after a couple of minutes.

react native animation , Easing.bounce force bounce only two times

Is it possible to for Easing.bounce to bounce only 2 times?
And not 3 times;
Animated.timing(
this.y_translate,
{
delay: 0,
toValue: 1,
easing: Easing.bounce,
duration: 1000,
}
).start();
});
Short answer is no.
Long answer is to look at the docs.
You'll see that Easing.bounce is based off of this mathematical definition that has the bounce happening 4 times. You can see exactly how they do this in their example code (note the easeInBounce, easeOutBounce, and easeInOutBounce functions). If you compare this with what is in the React Native source for Easing.bounce, you'll find the same mathematical calculations.
So if you want to have a two bounce effect, you'll need to do the math yourself. For example, you can create your own Easing class with it's own bounce method. Then use it in your animation in place of Easing.bounce.
// You can also extend Easing and just define a new method (or override)
// if you want access to Easing's other methods.
class MyEasing {
/**
* Provides a two bounce effect.
*/
static bounce(t: number): number {
/* Code Goes Here */
return something;
}
}
// ... in your code ...
Animated.timing(
this.y_translate,
{
delay: 0,
toValue: 1,
easing: MyEasing.bounce,
duration: 1000,
}
).start();
});
How you do this calculation though is outside the scope of the question, so I'll leave that for your to figure out.

It is so slow when a callback function be called repeatedly in react native app

It will have a callback function called repeatedly to when I start a download task. But It will be so slow that it can't give feedback when touch a button.
Fileio.downloadFile(downloadData[downloadFileIndex].uri, '1.jpg',this.progressFunc.bind(this)).then((DownloadResult)=> {
if (DownloadResult.statusCode == 200) {
let nextDownloadFileIndex = this.props.downloadFileIndex + 1;
this.props.dispatch(DOWNLOADED_A_FILE({
downloadFileIndex:nextDownloadFileIndex,
progressNum:0
}))
}
}).catch((error)=> {
console.log(error)
})
This is my code and the callback function are as be folllowed
progressFunc(DownloadBeginCallbackResult) {
let progressNum = DownloadBeginCallbackResult.bytesWritten / DownloadBeginCallbackResult.contentLength;
if(progressNum<=0.99){
this.props.dispatch(DOWNLOADING_A_FILE({
progressNum:progressNum,
jobId:this.props.jobId
}));
}else{
this.props.dispatch(DOWNLOADING_A_FILE({
progressNum:0,
jobId:this.props.jobId
}));
}
}
I mean I can't get feedback immediately when I touch button. I think that it is because I have a callback function called repeatedly. so js can't handle so many tasks;
It does sound like JS thread is busy doing the request and not able to communicate back to UI thread. One thing you can try is to wrap you on press handler in an InteractionManager.runAfterInteractions(() => ...)
See https://facebook.github.io/react-native/docs/interactionmanager.html