Moving an Image Along a Series of CGPoints

I have a path stored in an array of CGPoints that I would like to move. Here is the general code that I still have:

-(void)movePic:(id)sender{ for(int i = 0; i < self.array.count; i++){ CGPoint location = [[self.array objectAtIndex:i] CGPointValue]; [UIView animateWithDuration:0.1 animations:^{ self.imageView.center = location; } completion:^(BOOL finished){ }]; } } 

The problem is that the for loop is very fast, so you only see the animation at the last points. I'm not sure how best to do this. Ideally, what could I do to make one animation end before another? Should I use a for loop? Thanks

+5
source share
2 answers

Your code assumes that the UIView animation is executed synchronously in the main thread, but it is not.

It seems you have two options

  • Explicit CAKeyframeAnimation for animating CALayer along any number of sample points (interpolated between them)
  • Implicit recursive animation of a UIView to animate a UIView along a series of sample points (interpolated between them)

The former will be much more effective - yet I thought I should show you both options.

CAKeyframeAnimation

 - (void)movePic:(id)sender { //create a mutable core-graphics path CGMutablePathRef path = CGPathCreateMutable(); for(int i = 0; i < self.array.count; i++) { CGPoint location = [[self.array objectAtIndex:index] CGPointValue]; CGPathAddLineToPoint(path, nil, location.x, location.y); } //create a new keyframe animation CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; //add our path to it pathAnimation.path = path; //be nice to the system CGPathRelease(path); //setup some more animation parameters pathAnimation.duration = 0.1 * self.array.count; //add the animation to our imageView layer (which will start the animation) [self.imageView.layer addAnimation:pathAnimation forKey:@"pathAnimation"]; } 

UIView animation

 - (void)movePicToPointAtIndex:(unsigned int)index { //safeguard check... if ([self.array count] <= index) return; //get the next location CGPoint location = [[self.array objectAtIndex:index] CGPointValue]; //animate the imageView center towards that location [UIView animateWithDuration:0.1 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction animations:^{ self.imageView.center = location; } completion:^(BOOL finished){ //we are done with that animation, now go to the next one... [self movePicToPointAtIndex:index+1]; }]; } - (void)movePic:(id)sender { [self movePicToPointAtIndex:0]; } 
+4
source

Well, you need to set up an array of points as a property of the class, something like animationPath . So, now you will need to pay attention to the delegate methods of the UIView animation delegation methods (this is not a completely different class, it is just a delegate of class methods).

Set the way you call setAnimationDidStopSelector:selector every time the animation stops, so here you have something like this:

 //Inside the callback for setAnimationDidStopSelector if ([animationPath count] != 0){ //Go to next point CGPoint location = [[self.array objectAtIndex:0] CGPointValue]; [UIView animateWithDuration:0.1 animations:^{ self.imageView.center = location; } completion:^(BOOL finished){ }]; } else{ NSLog(@"Nowhere else to go, animation finished :D"); } 

So just remember to start the animation with the first point.

As far as I remember, the UIView animation manages things in other threads, so this is probably why the for statement doesn't work.

+2
source

Source: https://habr.com/ru/post/927295/


All Articles