How to animate and rotate an image? - objective-c

Hi i am working on an iPhone application and i have to animate and rotate an image, Image is attached here
now purpose of this image is that whenever any tap some where on iPad it will animate and will point towards that place.
Please help me to figure it out. Thanx

Try this -
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
animation.fromValue = [NSNumber numberWithFloat:0.0f];
animation.toValue = [NSNumber numberWithFloat: 2*M_PI];
animation.duration = 10.0f;
animation.repeatCount = INFINITY;
[self.yourImage.layer addAnimation:animation forKey:#"SpinAnimation"];

check this tutorial. It will really help you.

To animate images view, you'll need to use CoreAnimation.
All you have to do is making UIImageView object with your image inside and then you'll manipulate directly the layer to animate.
There is 2 kind of animation with core animation :
Implicit animation (normally they are activate by default) : Everytime you change some setting on the layer (like position with [imageView.layer setPosition:CGPointMake...]) there should be an implicit animation with default parameters (Duration, AnimationCurve etc.)
Explicit animation : If you want to create more complex animations, you should use explicit animation, it will allow you to do complex things like moving, rotating and scaling some layer in the same time.
I encourage you to check the core animation programming guide

Related

Smooth Animation on CAKeyframeAnimation for CATransform3D animations

I've created my own transition animation between views. I animate two properties, the position and the transform, to provide a cube-like transition between views. The frame uses CABasicAnimation while the transform uses a "2-stage" CAKeyframeAnimation. Everything works fine except for one small detail I can't seem to figure out. In my transition I apply a CATransform3DScale on the middle key frame to create a zoom-in/zoom-out effect. That works fine except the animation looks slightly jerky. It's animating the between the key frames in a linear fashion, and I would like to smooth that out. Now CAKeyframeAnimation has a way to do that using calculationMode, but it doesn't seem to work for transforms. I've tried setting it to kCAAnimationCubic and kCAAnimationCubicPaced with no effect.
Here is the code that animates one view's transform (a similar block of code animates the other view):
CAKeyframeAnimation *aTransform = [CAKeyframeAnimation animationWithKeyPath:#"transform"];
CATransform3D transform1 = RotateOnX(toView, M_PI_4);
transform1 = CATransform3DScale(transform1, RotationalZoom, RotationalZoom, RotationalZoom);
[aTransform setValues:Array([NSValue valueWithCATransform3D:RotateOnX(toView, M_PI_2)],
[NSValue valueWithCATransform3D:transform1],
[NSValue valueWithCATransform3D:RotateOnX(toView, 0)])];
[toView.layer addAnimation:aTransform forKey:#"transform"];
Note: RotateOnX(UIView *, CGFloat) is a block that returns a transform for a view rotated on X by the desired Radians.
As you can see I only set a scaling transform on the middle key frame. Also, the rotation of the view is perfectly smooth, it's only the scaling that appears to 'jerk' as it changes direction.
Does anyone have any ideas on how to smooth out the scaling/zooming?
Try the timingFunctions property. Since you have 3 keyframes, you need 2 timing functions: one for the animation from keyframe 0 to keyframe 1, and another for the animation from keyframe 1 to keyframe 2.
aTransform.timingFunctions = [NSArray arrayWithObjects:
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInOut],
nil];

wiggle animation in objective C

I have multiple animate-able/interactive UIImageViews on my UIView which would animate/interact based on user touches. I am trying to add a feature which would "wiggle" these animate-able/interactive UIImageViews on touch of an Icon which would help user in identifying which objects are interactive on screen. I am trying to use following code to achieve "wiggle" movement from this blog:
-(void)doWiggle:(UIView *)touchView {
// grabbing the layer of the tocuhed view.
CALayer *touchedLayer = [touchView layer];
// here is an example wiggle
CABasicAnimation *wiggle = [CABasicAnimation animationWithKeyPath:#"transform"];
wiggle.duration = 0.1;
wiggle.repeatCount = 1e100f;
wiggle.autoreverses = YES;
wiggle.toValue = [NSValue valueWithCATransform3D:CATransform3DRotate(touchedLayer.transform,0.1, 0.0 ,1.0 ,1.0)];
// doing the wiggle
[touchedLayer addAnimation:wiggle forKey:#"wiggle"];
// setting a timer to remove the layer
[NSTimer scheduledTimerWithTimeInterval: 2.0 target:self selector:#selector(endWiggle:) userInfo:touchedLayer repeats:NO];
}
-(void)endWiggle:(NSTimer*)wiggleTimer {
// stopping the wiggle now
[((CALayer*)wiggleTimer.userInfo) removeAllAnimations];
}
I call it like this in my routine :[self doWiggle:imageAnimation]; where imageAnimation is an UIImageView. I see that while wiggling, half of the image is disappearing. I read somewhere that I need to set the z-index properly in order for this to work. What do I need to set for z-index? and I have 3 to 4 UIImageViews per page where I need to call doWiggle: routine, do I need to fix z-indexes of all those UIImageViews?
Before you call doWiggle, you may need to do this code:
[[touchView superview] bringSubviewToFront:touchView];
If you can see the entire view before doing the animation then this will probably not fix your problem. It is possible that your image is being scaled by the image view and that is causing a problem during the animation. You may need to rescale your image, with an image editing program, to fit inside the view without having the view scale it. You can also do this programmatically, if you don't have a static image (i.e. loading off the network, etc).

Tracking a Core Animation animation

I have two circles which move around the screen. The circles are both UIViews which contain other UIViews. The area outside each circle is transparent.
I have written a function to create a CGPath which connects the two circles with a quadrilateral shape. I fill this path in a transparent CALayer which spans the entire screen. Since the layer is behind the two circular UIViews, it appears to connect them.
Finally, the two UIViews are animated using Core Animation. The position and size of both circles change during this animation.
So far the only method that I have had any success with is to interrupt the animation at regular intervals using an NSTimer, then recompute and draw the beam based on the location of the circle's presentationLayer. However, the quadrilateral lags behind the circles when the animation speeds up.
Is there a better way to accomplish this using Core Animation? Or should I avoid Core Animation and implement my own animation using an NSTimer?
I faced a similar problem. I used layers instead of views for the animation. You could try something like this.
Draw each element as a CALayer and include them as sublayers for your container UIVIew's layer. UIViews are easier to animate, but you will have less control. Notice that for any view you can get it's layer with [view layer];
Create a custom sublayer for your quadrilateral. This layer should have a property or several of properties you want to animate for this layer. Let's call this property "customprop". Because it is a custom layer, you want to redraw on each frame of the animation. For the properties you plan to animate, your custom layer class should return YES needsDisplayForKey:. That way you ensure -(void)drawInContext:(CGContextRef)theContext gets called on every frame.
Put all animations (both circles and the quad) in the same transaction;
For the circles you can probably use CALayers and set the content, if it is an image, the standard way:
layer.contents = [UIImage imageNamed:#"circle_image.png"].CGImage;
Now, for the quad layer, subclass CALayer and implement this way:
- (void)drawInContext:(CGContextRef)theContext{
//Custom draw code here
}
+ (BOOL)needsDisplayForKey:(NSString *)key{
if ([key isEqualToString:#"customprop"])
return YES;
return [super needsDisplayForKey:key];
}
The transaction would look like:
[CATransaction begin];
CABasicAnimation *theAnimation=[CABasicAnimation animationWithKeyPath:#"customprop"];
theAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(1000, 1000)];
theAnimation.duration=1.0;
theAnimation.repeatCount=4;
theAnimation.autoreverses=YES;
theAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
theAnimation.delegate = self;
[lay addAnimation:theAnimation forKey:#"selecting"];
[CATransaction setValue:[NSNumber numberWithFloat:10.0f]
forKey:kCATransactionAnimationDuration];
circ1.position=CGPointMake(1000, 1000);
circ2.position=CGPointMake(1000, 1000);
[CATransaction commit];
Now all the draw routines will happen at the same time. Make sure your drawInContext: implementation is fast. Otherwise the animation will lag.
After adding each sublayer to the UIViews's layer, rememeber to call [layer setNeedsDisplay]. It does not get called automatically.
I know this is a bit complicated. However, the resulting animations are better than using a NSTimer and redrawing on each call.
If you need to find the current visible state of the layers, you can call -presentationLayer on the CALayer in question, and this will give you a layer that approximates the one used for rendering. Note I said approximates - it's not guaranteed to be fully accurate. However it may be good enough for your purposes.

Animating the UIButton Layer?

I'm trying to bring the ripple effect seen in the dashboard application to iphone. My idea is whenever i place a button in the layout view there should be ripple effect around the button.
However, I`m able to bring the ripple effect for the whole view but I needs the effect only around the button. I don know where I went wrong. I tried the following code.
LayoutButton *tempLayoutButton=[[LayoutButton alloc] initWithObject:object];
tempLayoutButton.center=copyImage.center;
[layoutView addSubview:tempLayoutButton];
CALayer *templayer=[CALayer layer];
tempLayoutButton.layer.masksToBounds=NO;
templayer.frame=CGRectMake(0,0,50,50);
[tempLayoutButton.layer addSublayer:templayer];
CATransition *animation = [CATransition animation];
animation.delegate = self;
animation.duration = 1.0f;
animation.timingFunction = UIViewAnimationCurveEaseInOut;
animation.type = #"rippleEffect";
[templayer addAnimation:animation forKey:#"animation"];
[tempLayoutButton release];
[tempLayoutButton.layer addSublayer:templayer];
If I replace templayer with LayoutView layer I can see the riple effect from the whole view. Can anyone tell me the solution
Thanks in advance
I found the answer in one of apples mailing list. The animation is apple`s own animation and no one can use that. And there is no guarantee for the animation to appear properly in the screen. If we need the same type of animation we need to manipulate the layers and get the animation

CALayer explicit animations not behaving properly

Implicitly things behave fine. But when i try to use explicit animations to do multiple animations on a single layer (e.g. opacity and translation) I get odd results.
First of all, i tried using CATransaction. Then i switched to CAAnimationGroup. Both doesnt seem to get what i want.
What do I want?
All i want is for a layer to move from one point to another with an initial opacity and a target opacity. thats it!
What am i seeing?
Here is one example...
When performing a transaction begin/commit, the translation appears to be correct, but the opacity is not. My start opacity is 0, and the target opacity is 0.5.
However when i run the animations, it blends to 0.5, but then "snaps" to 1.0 (fully opaque).
I tried setting the removedOnCompletion to NO. but that didnt help either.
I think the bottom line is that i need to know the difference between an AnimationGroup and a Transaction.
Can anybody explain this, and possibly what im seeing regarding the oddness of my animations?
Thanks!
Ok, explicit animations arent working for me.
I tried creating a basic animation for opacity (of a layer). I placed this inside an animation group. When i execute, nothing happens. For simplicity i took out translation animations. This is only trying to do opacity animation.
CAAnimationGroup *group = [CAAnimationGroup animation];
CABasicAnimation *opacityAnimation;
opacityAnimation = [CABasicAnimation animationWithKeyPath:#"opacity"];
opacityAnimation.fromValue = [NSNumber numberWithDouble:fromalpha];
opacityAnimation.toValue = [NSNumber numberWithDouble:toalpha];
opacityAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
opacityAnimation.delegate = self;
opacityAnimation.duration = 2.7;
opacityAnimation.removedOnCompletion = NO;
group.animations = [NSArray arrayWithObjects: opacityAnimation, nil];
[baseLayer addAnimation:group forKey:#"groupAnim"];
You have to set the layers opacity to the value after the animation in explicit animations.
layer.opacity=0.0f;