how to stop CAKeyFrameAnimation in Iphone - iphone

hi iam currently working in simple amimation app in which i implement following code
CGMutablePathRef path = CGPathCreateMutable();
// CGPathMoveToPoint use to move position
CGPathMoveToPoint(path, NULL, 160, 90);
//move image to state x Axes Right
CGPathAddLineToPoint(path, NULL,-30, 90);
animation = [CAKeyframeAnimation animationWithKeyPath:#"position"];
animation.path = path;
CFRelease(path);
animation.duration = 15.0;
animation.repeatCount = 0;
animation.rotationMode = kCAAnimationPaced;
animation.removedOnCompletion = YES;
[[ballImageView1 layer] addAnimation:animation forKey:#"zposition"];
but my problem is that whenever animation is completed then anmation stop func

I'm not sure about your question. It sounds like your animation stopped and you what it to repeat indefinitely?
By setting repeatCount = 0, it will only go through the animation once.
You need to set repeatCount = HUGE_VALF to get it to repeat over an over.
repeatCount
Determines the number of times the animation will repeat.
#property float repeatCount
Discussion
May be fractional. If the repeatCount is 0, it is ignored. Defaults to 0. If both repeatDuration and repeatCount are specified the behavior is undefined.
Setting this property to HUGE_VALF will cause the animation to repeat forever.
If you just want the last frame of the animation to stay visible then set removedOnCompletion = NO.

Related

iOS "CABasicAnimation" brings component to the original position after animation complete

I'm animating UIImageView using iOS core animation "CABasicAnimation", all works fine for me but the only problem is when i animate to the position, after completeing animation it comes back to original position where it was. how can i overcome this? i need to keep UIImageView in moved position.
NOTE : I've seen few questions with success answers regarding this, but i have no idea why mine is not working like they say.
After rotating a CALayer using CABasicAnimation the layer jumps back to it's unrotated position
Here is my sample code,
CGPoint endPt = CGPointMake(160, 53);
CABasicAnimation *anim5 = [CABasicAnimation animationWithKeyPath:#"position"];
[anim5 setBeginTime:CACurrentMediaTime()+0.4];
anim5.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
anim5.fromValue = [NSValue valueWithCGPoint:imgRef.layer.position];
anim5.toValue = [NSValue valueWithCGPoint:endPt];
anim5.duration = 1.5;
anim5.speed = 2;
[imgRef.layer addAnimation:anim5 forKey:#"position"];
//this is what other answers ask to do
[anim5 setFillMode:kCAFillModeForwards];
[anim5 setRemovedOnCompletion:NO];
BTW [imgRef.layer setPosition:CGPointMake(160, 53)]; won't help me since i'm delaying animation with 4 milliseconds.
The root cause is that the animation just transitions the property between two values, it doesn't actually change the ending value. You need to change the ending value when the animation completes, there are three ways to do that.
1) Use the delegate property on the CAAnimation superclass to be notified of when the animation completes. At that point you can set the property to it's end value. See: https://developer.apple.com/library/mac/#documentation/GraphicsImaging/Reference/CAAnimation_class/Introduction/Introduction.html#//apple_ref/occ/cl/CAAnimation The animationDidStop:finished: is the method you'll need to implement on the delegate.
2) Set a completion block on the surrounding CATransaction. You'll need to manually start the CATransaction rather than having CABasicAnimation do that automatically for you. See: Objective-C - CABasicAnimation applying changes after animation?
3) See OMZ's comment below...
The right answer is to set the layer's position property, but as you've pointed out, it makes it more difficult because you're wanting a 0.4 second delay prior to the position change. Is there any reason you couldn't perform the delay first and then do the animation? Something like this:
- (IBAction)didTapMove:(id)sender
{
[self performSelector:#selector(animate) withObject:nil afterDelay:0.4];
}
- (void)animate
{
CGPoint endPt = CGPointMake(160, 53);
CABasicAnimation *anim5 = [CABasicAnimation animationWithKeyPath:#"position"];
anim5.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
anim5.fromValue = [NSValue valueWithCGPoint:_imageView.layer.position];
anim5.toValue = [NSValue valueWithCGPoint:endPt];
anim5.duration = 1.5;
anim5.speed = 2;
[_imageView.layer addAnimation:anim5 forKey:#"position"];
[_imageView.layer setPosition:CGPointMake(160, 53)];
}
Noticed I've removed your begin time from the animation since the delay is occurring in the perform selector call.

iOS; How to scale UIimageView (permanently) and then move it

I've hit a wall here. I know how to move an Image using "CGAffineTransformMakeTranslation" and I also know how to scale an image using"CGAffineTransformMakeScale" but for the life of me, I can't seem to get one Image to do both of these and stay that way. It scales to the desired size for about a split second and then immediately reverts to its original size and moves to the desired location. What I need is for the image to get big, STAY big, and then move to a new location (while permanently staying its new size).
Here is what I've got going on in my .m file:
-(IBAction)PushZoomButton {
[UIWindow animateWithDuration:1.5
animations:^{
JustinFrame.transform = CGAffineTransformMakeScale(2.0, 2.0);
JustinFrame.transform = CGAffineTransformMakeTranslation(10.0, 10.0);}];
[UIWindow commitAnimations];}
Any help with this would be appreciated!
you can use CGAffineTransformConcat, for instance:
JustinFrame.transform = CGAffineTransformConcat(CGAffineTransformMakeScale(2.0, 2.0), CGAffineTransformMakeTranslation(10.0, 10.0));
You may need to adapt the translation to (5, 5) since you have doubled the scale
The second transform you set overrides the first one. You need to concat both transform actions into one, as Luis said. Another way of writing that would be:
CGAffineTransform transform = CGAffineTransformMakeScale(2.0, 2.0);
transform = CGAffineTransformTranslate(transform, 10, 10);
JustinFrame.transform = transform;
You may need to look into CoreAnimation, basically what UIView animation is controlling under the hood. If you set up a CAAnimation, then what you want to achieve is done with the fillMode property of the animation.
Here's some example code to make a UIView look like it's opening like a door (copy pasted some code I have, but perhaps you could modify it and find it useful):
- (void) pageOpenView:(UIView *)viewToOpen duration:(NSTimeInterval)duration pageTurnDirection:(PageTurnDirection) p{
// Remove existing animations before stating new animation
[viewToOpen.layer removeAllAnimations];
// Make sure view is visible
viewToOpen.hidden = NO;
// disable the view so it’s not doing anythign while animating
viewToOpen.userInteractionEnabled = NO;
float dir = p == 0 ? -1.0f : 1.0f; // for direction calculations
// create an animation to hold the page turning
CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:#"transform"];
transformAnimation.removedOnCompletion = NO;
transformAnimation.duration = duration;
transformAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
CATransform3D startTransform = CATransform3DIdentity;
if (p == NEXT_PAGE) {
// orig values
startTransform.m34 = 0.001f;
}else {
// orig values
startTransform.m34 = -0.001f;
}
// start the animation from the current state
transformAnimation.fromValue = [NSValue valueWithCATransform3D:startTransform];
// this is the basic rotation by 90 degree along the y-axis
CATransform3D endTransform = CATransform3DMakeRotation(3.141f/2.0f,
0.0f,
dir,
0.0f);
// these values control the 3D projection outlook
if (p == NEXT_PAGE) {
endTransform.m34 = 0.001f;
endTransform.m14 = -0.0015f;
}else {
endTransform.m34 = -0.001f;
endTransform.m14 = 0.0015f;
}
transformAnimation.toValue = [NSValue valueWithCATransform3D:endTransform];
// Create an animation group to hold the rotation
CAAnimationGroup *theGroup = [CAAnimationGroup animation];
// Set self as the delegate to receive notification when the animation finishes
theGroup.delegate = self;
theGroup.duration = duration;
// CAAnimation-objects support arbitrary Key-Value pairs, we add the UIView tag
// to identify the animation later when it finishes
[theGroup setValue:[NSNumber numberWithInt:[(BODBookPageView *)viewToOpen pageNum]] forKey:#"animateViewPageNum"]; //STEPHEN: We set the tag to the page number
[theGroup setValue:[NSNumber numberWithInt: p] forKey:#"PageTurnDirection"];
[theGroup setValue:[NSNumber numberWithBool:YES] forKey:#"isAnimationMidpoint"]; // i.e. is this the first half of page-turning or not?
// Here you could add other animations to the array
theGroup.animations = [NSArray arrayWithObjects:transformAnimation, nil];
theGroup.removedOnCompletion = NO; // THIS LINE AND THE LINE BELOW WERE CRUCIAL TO GET RID OF A VERY HARD TO FIND/FIX BUG.
theGroup.fillMode = kCAFillModeForwards; // THIS MEANS THE ANIMATION LAYER WILL STAY IN THE STATE THE ANIMATION ENDED IN, THEREBY PREVENTING THAT ONE FRAME FLICKER BUG.
// Add the animation group to the layer
[viewToOpen.layer addAnimation:theGroup forKey:#"flipViewOpen"];
}

How do I animate CATransform3Ds with a CAKeyframeAnimation?

I've used CAKeyframeAnimations to animate a layer's transform.rotation and transform.translation.x properties, but I'm having trouble animating the transform property implicitly. I have a layer that must animate between two states and CABasicAnimation's default interpolation is totally incorrect and doesn't follow the path I want. CAKeyframeAnimation to the rescue, or so I thought. Any attempt to animate transform using a CAKeyframeAnimation results in the view immediately snapping to the final transform while the other animations run. If I remove the first half of the following function and let my "transform" events use the CABasicAnimation on the bottom, it animates just fine - albeit with incorrectly interpolated transforms along the way.
My layer delegate has implemented the following:
- (id <CAAction>) actionForLayer:(CALayer *)layer forKey:(NSString *)event
{
if ([event isEqualToString:#"transform"])
{
CGSize startSize = ((CALayer *)self.layer.presentationLayer).bounds.size;
CGSize endSize = self.layer.bounds.size;
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:event];
animation.duration = 0.25;
NSMutableArray *values = [NSMutableArray array];
int stepCount = 10;
for (int i = 0; i < stepCount; i++)
{
CGFloat p = i / (float)(stepCount - 1);
CGSize size = [self interpolateBetweenSize:startSize andSize:endSize percentage:p];
CATransform3D transform = [self transformForSize:size];
[values addObject:[NSValue valueWithCATransform3D:transform]];
}
animation.values = values;
return animation;
}
// All other animations use this basic animation
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:event];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.removedOnCompletion = YES;
animation.fillMode = kCAFillModeForwards;
animation.duration = 0.25;
return animation;
}
My transform is a translation followed by a rotate, but I think a group animation with separate keyframe animations animating through a translation AND a rotate would result in crazy town. I've confirmed that size & transform are correct for all values of p that I pass though, and p strictly ranges from 0 to 1.
I've tried setting a non-default timing function, I've tried setting an array of timing functions, I've omitted the keyTImes, I've set a repeatCount of 0, removedOnCompletion=YES, and a fillMode of forwards and that had no effect. Am I not creating the transform keyframe animation correctly?
This technique worked back in iOS 3 but seemed to be broken in iOS 5.0.
5.1 'magically' fixed this, it seemed to be a bug in iOS 5.0. I'd file a radar, but it is now working in 5.1.
#Gsnyder: Some background: I am experimenting with Clear-like UI (for something completely unrelated to Clear) and came up with this: http://blog.massivehealth.com/post/18563684407/clear. That should explain the need for a rotate & translate.
I've since created a shutter transition that subdivides a view into N layers (instead of just 2) that looks like this when viewed from the side: /////.
My code is not animating the bounds, it is using the size at each step to determine the necessary transform.
#Paul.s: Implicit allows me to keep this abstraction within the layer class itself without polluting the view controller that owns it. The view controller should just be changing the bounds around and the layer should move appropriately. I'm not a fan of view controllers having dozens of custom animations when the views themselves can handle it.
I need to use a keyframe animation because the default animation between layer transforms / and _ animate through incorrect angles so the ///\ layers do not line up throughout the transform. The keyframe animations ensure the edges all line up correctly while they all animate.
I'm considering this closed, this seems to be a bug in iOS 5.0 and has since been fixed. Thanks everyone.
(void)animateViewWith3DCurrentView:(UIView *)currentView withPoing:(CGPoint)movePoint
{
//flip the view by 180 degrees in its place first.
currentView.layer.transform = CATransform3DRotate(currentView.layer.transform,myRotationAngle(180), 0, 1, 0);
//set the anchor point so that the view rotates on one of its sides.
currentView.layer.anchorPoint = CGPointMake(0.5, 0.5);
//Set up scaling
CABasicAnimation *resizeAnimation = [CABasicAnimation animationWithKeyPath:kResizeKey];
//we are going to fill the screen here. So 423,337
[resizeAnimation setToValue:[NSValue valueWithCGSize:CGSizeMake(423, 337)]];
resizeAnimation.fillMode = kCAFillModeForwards;
resizeAnimation.removedOnCompletion = NO;
// Set up path movement
UIBezierPath *movePath = [UIBezierPath bezierPath];
//the control point is now set to centre of the filled screen. Change this to make the path different.
// CGPoint ctlPoint = CGPointMake(0.0, 0.5);
CGPoint ctlPoint = CGPointMake(1024/2, 768/2);
//This is the starting point of the animation. This should ideally be a function of the frame of the view to be animated. Hardcoded here.
// Set here to get the accurate point..
[movePath moveToPoint:movePoint];
//The anchor point is going to end up here at the end of the animation.
[movePath addQuadCurveToPoint:CGPointMake(1024/2, 768/2) controlPoint:ctlPoint];
CAKeyframeAnimation *moveAnim = [CAKeyframeAnimation animationWithKeyPath:kPathMovement];
moveAnim.path = movePath.CGPath;
moveAnim.removedOnCompletion = YES;
// Setup rotation animation
CABasicAnimation* rotateAnimation = [CABasicAnimation animationWithKeyPath:kRotation];
//start from 180 degrees (done in 1st line)
CATransform3D fromTransform = CATransform3DMakeRotation(myRotationAngle(180), 0, 1, 0);
//come back to 0 degrees
CATransform3D toTransform = CATransform3DMakeRotation(myRotationAngle(0), 0, 1, 0);
//This is done to get some perspective.
CATransform3D persp1 = CATransform3DIdentity;
persp1.m34 = 1.0 / -3000;
fromTransform = CATransform3DConcat(fromTransform, persp1);
toTransform = CATransform3DConcat(toTransform,persp1);
rotateAnimation.toValue = [NSValue valueWithCATransform3D:toTransform];
rotateAnimation.fromValue = [NSValue valueWithCATransform3D:fromTransform];
//rotateAnimation.duration = 2;
rotateAnimation.fillMode = kCAFillModeForwards;
rotateAnimation.removedOnCompletion = NO;
// Setup and add all animations to the group
CAAnimationGroup *group = [CAAnimationGroup animation];
[group setAnimations:[NSArray arrayWithObjects:moveAnim,rotateAnimation, resizeAnimation, nil]];
group.fillMode = kCAFillModeForwards;
group.removedOnCompletion = NO;
group.duration = 0.7f;
group.delegate = self;
[group setValue:currentView forKey:kGroupAnimation];
[currentView.layer addAnimation:group forKey:kLayerAnimation];
}

UIView animations in board game

Hello I am trying to create snakes and ladder type board game. and I am moving player pieces with UIView animations.But it is moving player pieces with shortest path it found. I want to move player pieces horizontally , vertical and diagonally .I used below code
[UIView animateWithDuration:1.0f
animations:^{
playerOneImage.center = boardView.center;
// Here you can disable the game play so that while animation is in progress, player cannot do other operations like rotating the dice, etc...
}
completion:^(BOOL finished){
if(finished) {
NSLog(#"Player moved to square:");
// Here you can enable the game play that disabled when animation started...
}
} ];
Please help
Use a CAKeyframeAnimation on the view's layer, instead of using +[UIView animateWithDuration:...].
First, you may need to add the QuartzCore framework to your target. If you don't know how to do that, read How to "add existing frameworks" in Xcode 4? Also add #import <QuartzCore/QuartzCore.h> to your app's .pch header file.
Now you can animate the view along a path. First, create a UIPath for the path you want the view to follow. This example will move the view to the right 50 points, and then down 100 points:
CGPoint position = self.playerOneImage.layer.position;
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:position];
position.x += 50; [path addLineToPoint:position];
position.y += 100; [path addLineToPoint:position];
Next, create a CAKeyframeAnimation that will animate the position property along that path:
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:#"position"];
animation.duration = 1.0f;
animation.path = path.CGPath;
animation.calculationMode = kCAAnimationPaced;
There are lots of options for changing the speed at which the layer moves along the path - check the docs.
Next, you have to set the layer's position to the final position, where you want it to be after the animation is over. It seems weird, but it's absolutely necessary:
// Important: you must actually set the layer's position!
// Otherwise the animation will put it back at the start
// when the animation ends. You should set the layer's
// final position, then add the animation.
self.playerOneImage.layer.position = position;
Finally, add the animation to the layer:
[self.playerOneImage.layer addAnimation:animation forKey:#"position"];
And you're done.
All together for easy cut/paste:
CGPoint position = self.playerOneImage.layer.position;
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:position];
position.x += 50; [path addLineToPoint:position];
position.y += 100; [path addLineToPoint:position];
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:#"position"];
animation.duration = 1.0f;
animation.path = path.CGPath;
animation.calculationMode = kCAAnimationPaced;
// Important: you must actually set the layer's position!
// Otherwise the animation will put it back at the start
// when the animation ends. You should set the layer's
// final position, then add the animation.
self.playerOneImage.layer.position = position;
[self.playerOneImage.layer addAnimation:animation forKey:#"position"];

CABasicAnimation not animating my property

I've been trying to understand what is wrong with my animation and I still haven't figure it out. I think it should be really straight forward, but there is probably something I'm missing, even after reading lot of examples and documentation.
My problem comes originally form the fact that on the iPhone, you cannot resize layers automatically (with the view). The documentation says otherwise but there is no autoresizeMask for the layer in the SDKs. So I decided to make a little workaround and animate the layer myself.
I've got this simple piece of code that should do a simple resize animation. The values are good and I even set the delegate in order to trace if the anim start/end.
// I've got a property named layerImage (which is a CALayer)
- (void)animateTestWithFrame:(CGRect)value {
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"layerImage.frame"];
animation.duration = 1;
animation.fromValue = [NSValue valueWithCGRect:self.frame];
animation.toValue = [NSValue valueWithCGRect:value];
animation.removedOnCompletion = YES;
animation.delegate = self;
[self.layer addAnimation:animation forKey:#"layerImage.frame"];
}
So, any ideas? (This view that contains the code is the subview of a subview of the window if that could make a difference)
--- EDIT ---
It seems that frame is not animatable via CABasicAnimation and the named property "frame". When using bounds, I've got some strange result, but at least I'm getting something. Will continue investigating on this.
So it's good that you've figured things out here, but your answer to your own question has some inaccuracies. Let me correct a few things:
The frame property can be animated--just not with explicit animation. If you do the following to a layer other than the root layer of a view, the frame will animate just fine:
[CATransaction begin];
[CATransaction setAnimationDuration:2.0f];
[animationLayer setFrame:CGRectMake(100.0f, 100.0f, 100.0f, 100.0f)];
[CATransaction commit];
Remember that setting a property on a layer will animate that property change by default. In fact you have to disable animations on a property change if you don't want it to animate. (Of course this is only true if you are animating a layer other than the root layer of a view.) You are correct in animating both position and bounds if you need to use an explicit animation.
You can animate the frame on a UIView using implicit animation:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:3.0f];
[[self view] setFrame:CGRectMake(45.0f, 45.0f, 100.0f, 100.0f)];
[UIView commitAnimations];
This will animate from the view's current frame (bounds and position) to x = 45.0, y = 45.0, w = 100.0, h = 100.0.
It seems you may also be misunderstanding the difference between an animation and a layer. You add animations to layers, but adding an animation to a layer does not automatically set the property that you're animating.
CALayers are model objects. They contain information about the layer that eventually gets rendered to screen. You must set a layer's property if you want that property to actually have that value. If you simply animate the property, it will only be a visual representation and not actual--which is to say this is why the value snaps back to the original value of the layer because you never actually changed it.
Which leads me to the next point. You said:
Use "animation.removedOnCompletion =
NO; animation.fillMode =
kCAFillModeForwards;" to ensure that
the values are not reseted at the end
of the animation
This is not exactly right. These two values simply cause the animation to remain at it's final position visually, however, the layer's actual values have not changed. They are still the exact same values they were when you started the animation. In general (with a few exceptions) you don't want to use these two parameters because they are visual only. What you want is to actually set the layer value for the property you're animating.
Say, for example, that you want to animate the position of your layer using an explicit animation. Here is the code you want:
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"position"];
[animation setFromValue:[NSValue valueWithCGPoint:CGPointMake(70.0f, 70.0f)]];
[animation setToValue:[NSValue valueWithCGPoint:CGPointMake(150.0f, 150.0f)]];
[animation setDuration:2.0f];
// Actually set the position on the *layer* that you want it to be
// when the animation finishes.
[animationLayer setPosition:CGPointMake(150.0f, 150.0f)];
// Add the animation for the position key to ensure that you
// override the animation for position changes with your animation.
[animationLayer addAnimation:animation forKey:#"position"];
You may also want to consider animation grouping. With an animation group, you can group several animations together and then control how they relate to each other. In your case the duration for your bounds and position animations are the same and so what you are trying to do will work fine without a group, but if you wanted to offset the start of the animations, for example you didn't want the position animation to start until a second or two into the frame animation, you could stagger them by setting the beginTime value of the position animation.
Finally, I would be curious to know why you couldn't use the implicit animations available on UIView. I use these in the vast majority of the Core Animation code I write and can't see why this wouldn't work for your situation.
Best regards.
The key path should only be the key path of the property, not the name of the object as well.
Use this
[CABasicAnimation animationWithKeyPath:#"frame"]
instead of this
[CABasicAnimation animationWithKeyPath:#"layerImage.frame"]
And just BTW, when you add animation to a layer, the key doen't mean the key property to animate. Just the key (name) that you want this animation to have (this refers to the last line your code)
So, the solution was to animate the #"bounds" and the #"position" of the layer because frame is not animatable on iPhone. It took me some time to understand that the position was the center of the layer and the resize of the bounds was extending from the center, but that was the easy part.
So, what I did in resume was:
In the setFrame, create 2 animations with the bounds and position property.
Use "animation.removedOnCompletion = NO; animation.fillMode = kCAFillModeForwards;" to ensure that the values are not reseted at the end of the animation
Register the delegate to self in order to implements "animationDidStop:finished:". It seems that you still need to set the values: "layerImage.bounds = [animation.toValue CGRectValue]; layerImage.position = [animation.toValue CGPointValue];".
I wasn't able to use the UIView animation system directly because it wasn't doing what I wanted on the layers.
Thanks tadej5553 for pointing me out the layer problem I had with the "addAnimation". So here is the code for those who would like to see what it looks like.
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
CABasicAnimation *animation = (CABasicAnimation*)anim;
if ([animation.keyPath isEqualToString:#"bounds"]) {
layerImage.bounds = [animation.toValue CGRectValue];
} else if ([animation.keyPath isEqualToString:#"position"]) {
layerImage.position = [animation.toValue CGPointValue];
}
}
- (void)setFrame:(CGRect)value {
CGRect bounds = CGRectMake(0, 0, value.size.width, value.size.height);
if ([UIView isAnimationStarted]) {
// animate the bounds
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"bounds"];
animation.duration = [UIView animationDuration];
animation.fromValue = [NSValue valueWithCGRect:layerImage.bounds];
animation.toValue = [NSValue valueWithCGRect:bounds];
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.timingFunction = [UIView animationFunction];
animation.delegate = self;
[layerImage addAnimation:animation forKey:#"BoundsAnimation"];
// animate the position so it stays at 0, 0 of the frame.
animation = [CABasicAnimation animationWithKeyPath:#"position"];
animation.duration = [UIView animationDuration];
animation.fromValue = [NSValue valueWithCGPoint:layerImage.position];
animation.toValue = [NSValue valueWithCGPoint:CGPointMake(bounds.size.width / 2, bounds.size.height / 2)];
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.timingFunction = [UIView animationFunction];
animation.delegate = self;
[layerImage addAnimation:animation forKey:#"PositionAnimation"];
} else {
layerImage.frame = bounds;
}
[super setFrame:value];
}