4
votes

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;
3
Nope, its set to YES on the layer being animated.bellissimo
Unfortunately, it made no difference.bellissimo

3 Answers

0
votes

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];
0
votes

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.

0
votes

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?