How to scale and rotate a view in a single animation - iphone

I am trying to present a view by making it emerge from the centre of the screen while growing to its full size, while also rotating it around the x-axis in a 3D manner. When I create the view I apply a transform to it to make sure it is shrunk and rotated to start off with (it is so small it is not actually visible), then I try to use a CATransform3D like this:
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:#"transform"];
CATransform3D transform = CATransform3DRotate(view.layer.transform, M_PI, 1.0, 0, 0);
transform = CATransform3DScale(transform, 1000, 1000, 1000);
transform.m34 = 1.0 / 10000;
[anim setToValue:[NSValue valueWithCATransform3D:transform]];
[anim setDuration:0.75f];
anim.removedOnCompletion = NO;
anim.delegate = self;
[view.layer addAnimation:anim forKey:#"grow"];
However this animation does not change the actual transform of the layer, so I also do this:
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
view.layer.transform = CATransform3DIdentity;
[view.layer removeAllAnimations];
}
to set the transform once the animation stops. However this sometimes results in a noticeable flicker at the end of the animation. I believe this is because the animation puts the original transform back at the end of the animation phase and this happens momentarily before the animationDidStop routine gets called. Is there a better way to do this?
Edit: Incorporating it into a UIView animation works as this way you can set the transform directly:
view.layer.transform = CATransform3DScale(CATransform3DIdentity, 0.001, 0.001, 0.001);
view.layer.transform = CATransform3DRotate(view.layer.transform, M_PI, 1.0, 0.0, 0.0);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.75];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
CATransform3D transform = CATransform3DRotate(view.layer.transform, M_PI, 1.0, 0, 0);
transform = CATransform3DScale(rotationTransform, 1000, 1000, 1000);
transform.m34 = 1.0 / -500;
view.layer.transform = transform;
[UIView commitAnimations];
However, I would still like an answer to my original query, as to how to achieve the same successully using a CAAnimation, as that provides more flexibility for animations generally.
Edit2: It seems the answer to my original question (how to fix the problem with the CAAnimation) was actually very straightforward. To keep the end state (and remove the flicker), I just needed to add the following line:
anim.fillMode = kCAFillModeForwards;

This might help you:
animationView.layer.anchorPoint = CGPointMake(0.0f, 0.0f);
animationView.center = CGPointMake(0,
(animationView.center.y -
(animationView.bounds.size.height/2.0f)));
// start the Page Open
[UIView beginAnimations:#"Animation" context:nil];
[UIView setAnimationDuration:2.0];
// set angle as per requirement
[animationView.layer setValue:[NSNumber numberWithInt:180]
forKeyPath:#"transform.rotation.x"];
[UIView commitAnimations];

I know this is not a clean and short answer you were probably hoping for :)
But here (UIView Animation Tutorial: Practical Recipes
) you can find a downloadable example which also shows how to do scale & rotate.
You can see the scale and rotate if you run the example, click HUD and then click stop.

See this thread about how iPad app store does the rotate and scale for an answer and code : How can I flip and enlarge a UIView it at the same time like iOS 7 iPad App Store?

Related

How to create a rotating circle?

I'm trying to make a simple "rotating gear animation." Basically, I want to put a circle on the screen at a certain position, and give this circle an image of gear (or just make the image rotating without creating a circle at first). Also, the gear should keep rotating. How can I achieve that?
I'm beginner to ios development. If anyone can provide a simple sample code, I will really appreciate that!
You have to actually rotate a UIImageView infinitely.
Firstly #import <QuartzCore/QuartzCore.h>
- (void) runSpinAnimationOnView:(UIView*)view duration:(CGFloat)duration rotations: (CGFloat)rotations repeat:(float)repeat;
{
CABasicAnimation* rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 /* full rotation*/ * rotations * duration ];
rotationAnimation.duration = duration;
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = repeat;
[view.layer addAnimation:rotationAnimation forKey:#"rotationAnimation"];
}
Assume that you have a UIImageView and assign an image on it and named ImgView. On viewDidLoad, add your code as below:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView setAnimationRepeatCount:MAXFLOAT];
ImgView.transform = CGAffineTransformMakeRotation(M_PI);
[UIView commitAnimations];
From the links :-
UIView Infinite 360 degree rotation animation?
Infinite rotating image background UIImageView

change uiview frame from both sides

Hello i want to make animation of a frame change. But i don't find nothing similar on the internet. I know how to animate the frame change, but the tricky part is that for example i have a square and i want it to shrink to the center. So how do i change frame to achieve that?
Do i have to change the frame width and height and also the origin of the frame, or maybe there is some simpler solution?
Any help or references on how to do it would be very appreciated!
Thanks in advance!
CGRect previousRect = view.layer.bounds;
CGRect newRect = previousRect;
newRect.size = size; // In your case define the new size (CGSize size)
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"bounds"];
animation.fromValue = [NSValue valueWithCGRect:previousRect];
animation.toValue = [NSValue valueWithCGRect:newRect];
[view.layer addAnimation:animation forKey:#"bounds"];
If you need the View Shrinking Code, here it is.
myView.transform=CGAffineTransformMakeScale(0.1, 0.1);
[UIView beginAnimations:#"animationExpand" context:NULL];
[UIView setAnimationDuration:0.4];
myView.transform=CGAffineTransformMakeScale(1, 1);
[UIView setAnimationDelegate:self];
[UIView commitAnimations];
This is for making the View larger. If you want to make view shrink smaller then just replace the transform lines with each other.
Hope it helps! :)
Set the frame before beginning the animation and inside the animation block change the frame to point to center of the actual frame. You need to set height/width as well as origin for that. That's how it is normally done.
You need use a center of view:
CGPoint *center = view.center;
view.frame = CRectMake (0,0,100,200); //set new frame;
view.center = center;
// here you should start animation

Display the Image like Fade In using CABasicAnimation

I am rotating the Image 360 clockwise using the CABasicAnimation, and the code which I am using is
CALayer* _caLayer = [CALayer layer];
_caLayer.contents = (id)_logo.CGImage;
_caLayer.frame = CGRectMake(65,158, 180,55);
[self.view.layer addSublayer:_caLayer];
CABasicAnimation* rotation;
rotation = [CABasicAnimation animationWithKeyPath:#"transform.rotation"];
rotation.fromValue = [NSNumber numberWithFloat:0];
rotation.toValue = [NSNumber numberWithFloat:((360*M_PI)/180)];
rotation.duration = 1.4f;
//rotation.beginTime = CACurrentMediaTime() +1;
rotation.repeatCount = 2.0;
rotation.fillMode = kCAFillModeForwards;
[_caLayer addAnimation:rotation forKey:#"360"];
The animation is working fine.. But I cant figure out one thing. I want to start animate the image from smaller size and ends with the normal size. You have seen in movies like some newspapers will rotate fast and they fade in and finally we will see the paper in the screen fully. I am trying to do that way. I dont know how to do it, please !
You can use the following also, will works like a charm
[UIView beginAnimations:#"fade in" context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
_imageView.alpha = 0.0;
_newImageView.alpha = 1.0;
[UIView commitAnimations];
Set the imageView frame before animation: [imageView setFrame: CGRectMake(your Frame)];
then keep on increasing the frame in the animation using a loop or something..

zooming from a particular point

I am using this code to zoom from a particular point
CGPoint getCenterPointForRect(CGRect inRect)
{
CGRect screenRect = [[UIScreen mainScreen] bounds];
return CGPointMake((screenRect.size.height-inRect.origin.x)/2,(screenRect.size.width-inRect.origin.y)/2);
}
-(void) startAnimation
{
CGPoint centerPoint = getCenterPointForRect(self.view.frame);
self.view.transform = CGAffineTransformMakeTranslation(centerPoint.x, centerPoint.y);
self.view.transform = CGAffineTransformScale( self.view.transform , 0.001, 0.001);
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:kTransitionDuration];
self.view.transform = CGAffineTransformIdentity;
[UIView commitAnimations];
}
Its not working. What is the correct way to do zooming from a particular point.
I think that, if I've diagnosed your problem correctly, you're getting a scaling animation where the view starts tiny and at a point, then scales and moves to the centre of the screen exactly like you want, but the point it starts at is incorrect?
First of all, views scale around their centre. So if you took out the translation and hence reduced the code you have to:
self.view.transform = CGAffineTransformMakeScale( 0.001, 0.001);
And your view ends up taking up the whole screen then it'll remain centred on the middle of the screen, sort of a little as though it's a long way away and you're heading directly towards it.
Supposing you instead want it to grow and move to the centre of the screen from (x, y) then you need something more like:
CGPoint locationToZoomFrom = ... populated by you somehow ...;
CGPoint vectorFromCentreToPoint = CGPointMake(
locationToZoomFrom.x - self.view.center.x,
locationToZoomFrom.y - self.view.center.y);
self.view.transform = CGAffineTransformMakeTranslation(vectorFromCentreToPoint.x, vectorFromCentreToPoint.y);
self.view.transform = CGAffineTransformScale( self.view.transform , 0.001, 0.001);
Where locationToZoomFrom will be the initial centre of the view and its normal centre as per its frame will be the destination.

Can you perform/animate 2transforms on a layer at the same time?

[UIView beginAnimations:#"trans" context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(moveCardToSide)];
[UIView setAnimationDuration:1.0];
CGRect frame = playersCard.view.layer.frame;
frame.origin.x = -30;
playersCard.view.layer.frame = frame;
playersCard.view.layer.transform = CATransform3DScale(playersCard.view.layer.transform, 0.7, 0.7, 1.0);
playersCard.view.layer.transform = CATransform3DRotate(playersCard.view.layer.transform, 30*M_PI/180, 0.0, 1.0, 0.0);
[UIView commitAnimations];
Both of the above transforms are performed. But only the 2nd once is animated. They both animate if i run them separately. It is possible to combine them into 1 animation?
Whats happening with the scale is that it jumps from 100% size to 70% then animates the rotate.
As you've written it, the transformations are being combined into a single animation. If you want two animations, with the second occurring right after the first simply move your second transform adjustment into an UIView animation block in -moveCardToSide