3

Maybe someone can point me in the right direction. I tried Google but dont really know how to define my question in searchable terms.

I am animating an image along a UIBezierPath like this:

UIBezierPath *trackPath = [UIBezierPath bezierPath];
[trackPath moveToPoint:P(8, 250)];
[trackPath addCurveToPoint:P(318, 250)
             controlPoint1:P(156, 86)
             controlPoint2:P(166, 412)];
[trackPath addCurveToPoint:P(652, 254)
             controlPoint1:P(488, 86)
             controlPoint2:P(512, 412)];
[trackPath addCurveToPoint:P(992, 254)
             controlPoint1:P(818, 96)
             controlPoint2:P(872, 412)];


CALayer *bee = [CALayer layer];
bee.bounds = CGRectMake(0, 0, 69, 71);
bee.position = P(160, 25);
bee.contents = (id)([UIImage imageNamed:@"bee3.png"].CGImage);
[self.view.layer addSublayer:bee];

What I want to do is animate the image itself as it moving along the path. I can animate the image when its b itself with like this:

    NSArray *blueArray = [NSArray array];
    blueArray = [[NSArray alloc] initWithObjects:
                 [UIImage imageNamed:@"blue1.png"],
                 [UIImage imageNamed:@"blue2.png"], nil];

    blueFly.animationImages = blueArray;
    blueFly.animationDuration = 0.20;
    blueFly.animationRepeatCount = -1;
    [blueFly startAnimating];

How can I combine the two, so to speak?

Additionally I know how to draw the path itself onto the screen like this:

CAShapeLayer *beeline = [CAShapeLayer layer];
beeline.path = trackPath.CGPath;
beeline.strokeColor = [UIColor whiteColor].CGColor;
beeline.fillColor = [UIColor clearColor].CGColor;
beeline.lineWidth = 2.0;
beeline.lineDashPattern = [NSArray arrayWithObjects:[NSNumber numberWithInt:6],   [NSNumber numberWithInt:2], nil];
[self.view.layer addSublayer:beeline];

But how can I draw the line only behind the image as its being animated along the path?

Wesley Smith
  • 19,401
  • 22
  • 85
  • 133

2 Answers2

3

You can use a CAShapeLayer to display the path. A shape layer provides two properties strokeStart and strokeEnd that have values between 0 and 1 and determine the fraction of the path that is visible. By animating strokeEnd you can create the impression that the path is "drawn" on the screen. See http://oleb.net/blog/2010/12/animating-drawing-of-cgpath-with-cashapelayer for an example that animates a pen that draws a line.

In order to change the image of the bee you can simply add an animation that changes the contents of your bee layer. For example, to change the image of the pen in the CAShapeLayer project above, we can add the following code to the startAnimation method.

CAKeyframeAnimation *imageAnimation = [CAKeyframeAnimation animationWithKeyPath:@"contents"];
imageAnimation.duration = 1.0;
imageAnimation.repeatCount = HUGE_VALF;
imageAnimation.calculationMode = kCAAnimationDiscrete;
imageAnimation.values = [NSArray arrayWithObjects:
  (id)[UIImage imageNamed:@"noun_project_347_1.png"].CGImage,
  (id)[UIImage imageNamed:@"noun_project_347_2.png"].CGImage,
  nil];
[self.penLayer addAnimation:imageAnimation forKey:@"contents"];

This simply adds a key animation to the contents property of the layer that displays the pen. Note that the image "noun_project_347_1.png" is not part of the project so you would have to add an image to see the effect. I have simply horizontally flipped the image that comes with the project. By setting calculationMode to kCAAnimationDiscrete the animation does not interpolate between two images by replaces one by the other.

Jan Christiansen
  • 3,153
  • 1
  • 19
  • 16
  • Thanks Jan, Im going to dive into that example sounds perfect!. One other thing Ive run into is how can I dismiss all of the animations once im done with them? I have a timer set to call a method named masterReset after 7 seconds which gives the animation time to play out but Im not sure how to dissmis the layers Ive created. – Wesley Smith Sep 04 '12 at 09:18
  • I am not sure I understand what you are after, but you can remove all animations from a layer by invoking `removeAllAnimations`. Alternatively, you can use `removeAnimationForKey:` to remove a specific animation. If you have to handle the coordination of several animations, like pausing an animation until another one has completed, have a look at http://wangling.me/2011/06/time-warp-in-animation/. It was quite helpful to me. – Jan Christiansen Sep 04 '12 at 09:45
  • Thanks again for your time. I have adjusted the repeatCount to 0 on the CAKeyframAnimation which now makes the bee itself disappear after it gets to the end point but I want to remove the *beeline at the same time. i tried [self.view.layer removeAllAnimations]; but that doesnt work. I guess what Im realy trying to dismiss/remove is the CAShapeLayer *beeline. – Wesley Smith Sep 04 '12 at 10:58
  • You can simply remove the `CAShapeLayer` from its parent layer or set the `strokeEnd` to `0` if you want to use the layer for another animation. – Jan Christiansen Sep 04 '12 at 11:14
  • Yeah thats what Im reading but im not sure how to do that. The problem is I want to do this from another method namely my "masterReset" method. but when I try to do [beeline removeFromSuperlayer]; from this method beeline is not recognized. What do I need to do to be able to call the from outside of the method that created the layer? – Wesley Smith Sep 04 '12 at 11:26
  • If both methods are methods of the same object you, for example, can add an instance variable to the object that keeps a reference to the layer. I am sorry, but it appears to me that you should have a look at some basic tutorials about object oriented programming. – Jan Christiansen Sep 04 '12 at 13:15
  • Dont be sorry, you are right. I am just starting out with programming. I have a little experience in HTML and CSS but thats about it. I have been watching all of the videos on Lynda.com about Objective C and have learned a lot but my knowledge is very basic and I dont quite understand how all the different components interact. Ive just been making a bunch of really small apps focusing on one thing at a time. I ran across a BezierPath animation example and just wanted to see how all the animations did their thing. – Wesley Smith Sep 04 '12 at 15:07
  • Its been fun playing with it and I have learned some but its a little outta my league still. Thanks for your time, it is appreciated. – Wesley Smith Sep 04 '12 at 15:07
  • After some sleep I realized that I was making the last part way more difficult than it had to be and adapted my code to create a second view, add the layers to that view, then simply remove than view when the animation ends. :) – Wesley Smith Sep 05 '12 at 07:21
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/16306/discussion-between-delightedd0d-and-jan-christiansen) – Wesley Smith Sep 05 '12 at 14:54
  • @JanChristiansen: Cool. I did not know that you could use an array of images as content in a keyframe animation. Thanks for that nugget. – Duncan C Sep 07 '12 at 01:29
0

As long as you can get the exact path that you want to animate the image align you can do it using Core Animation and CAKeyframeAnimation.

Refer how-to-animate-one-image-over-the-unusual-curve-path-in-my-ipad-application) link.

Community
  • 1
  • 1
Paresh Navadiya
  • 38,095
  • 11
  • 81
  • 132
  • Thanks Prince, thats actually one of the one references I was able to find before posting but what part of that example animates the image itself? What I have is 2 pictures of a bee one with wings up and one with wings down and I want to switch between the two images as its being animated along the path so it looks like the wings are flapping – Wesley Smith Sep 04 '12 at 05:40