Reputation: 761
I'm simulating some effects, like leafs falling, snow and rain. My first call was to use CAEmitterLayer, that works very well, but i need to render the layer in context to save as an image, and that seens impossible or, at least, very complicated.
So i am working with some view animations. I need to continuously animate my imageViews so it can fall through screen and reappear on top of it, each one with diffenrent speed.
So i relocate each imageView on screen with animateWithDuration
and when animation is done i call the method that do that recursively from completion block so the imageview can make it's way to the end of screen. Once an imageView reachs the end of screen i relocate it on top.
The problem is when animation is over my imageView stops a little bit until the completion block calls the method recursively, i want it to be continuously.
My code generates random position for each imageView, and my animation duration is very short so i can always update imageView's location in case the user tap the button to save the view as an image.
Anyway, here is my code:
- (void)effectOnObject:(UIImageView *)object{
NSInteger initialX;
NSInteger initialy;
CGFloat duration;
//the object have reached the end of screen
if (object.frame.origin.y >= self.frame.size.height) {
//generate random position to relocate the object on x axis
initialX = arc4random() % 321;
//generate random position to relocate the object on y axis (little bit above top of screen)
initialy = ((NSInteger)-object.frame.size.height) - arc4random() % 11;
//duration 0 so the object can be replaced without animation
duration = 0.0;
}
else{
initialX = object.frame.origin.x;
//this change the speed of object
initialy = object.frame.origin.y + 10
//setted duration to short time
duration = 0.01;
}
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionAllowAnimatedContent
animations:^{
[object setFrame:CGRectMake(initialX, initialy, object.frame.size.width, object.frame.size.height)];
}
completion:^(BOOL completed){
//recursively call
[self effectOnObject:object];
}];
}
- (void)startEffect{
//initiate effect on each imageView
for (UIImageView *object in self.subviews) {
[self effectOnObject:object];
}
}
How can i make this animation repeatedly and continuously, without the gap when the method is called recursively from completion block and the animation restarts?
Upvotes: 0
Views: 1268
Reputation: 9915
You don't need to do the animation with 0 duration when the object reaches the end of the screen. Just test for this in your completion block and relocate the view before calling recursively. Also, a duration of 0.01 seems a bit extreme (100 frames per second). Perhaps a more reasonable value like 0.1 would help.
Something like this:
- (void)effectOnObject:(UIImageView *)object{
//setted duration to short time
CGFloat duration = 0.1;
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionAllowAnimatedContent
animations:^{
NSInteger initialX = object.frame.origin.x;
//this change the speed of object
NSInteger initialy = object.frame.origin.y + 10;
[object setFrame:CGRectMake(initialX, initialy, object.frame.size.width, object.frame.size.height)];
}
completion:^(BOOL completed){
NSInteger initialX = arc4random() % 321;
//generate random position to relocate the object on y axis (little bit above top of screen)
NSInteger initialy = ((NSInteger)-object.frame.size.height) - arc4random() % 11;
[object setFrame:CGRectMake(initialX, initialy, object.frame.size.width, object.frame.size.height)];
//recursively call
[self effectOnObject:object];
}];
}
Upvotes: 1
Reputation: 22972
From what I read briefly you should check out CAReplicatorLayer
. It is perfect for repeating stuff! Only issue I can think of is that the transform and values have to be incremental...
Upvotes: 0