Rotate UIView around right side of screen

1.3k views Asked by At

I want to rotate a view around the right edge of the screen, like a door opening. This is what I have so far:

CATransform3D transform = CATransform3DIdentity;
transform.m34 = -1.0f/500;
view.layer.transform = CATransform3DRotate(transform, kDegreesToRadians(90), 0, 1, 0);
[UIView animateWithDuration:2.0f animations:^{
     view.layer.transform = transform;
} completion:nil];

I'm not totally solid on CATranforms yet or matrices for that matter so if someone could push me in the right direction, it'd be much appreciated!

2

There are 2 answers

0
Duncan C On BEST ANSWER

UIView animations are for animating the properties of a view, not for animating layers. To the best of my knowledge, you can't animate a view's layer using a UIView animateWithDuration: call.

You'll need to create a CABasicAnimation and add it to your view's layer yourself.

It's been a while since I've done CAAnimations, but let's see what I can dig up:

As atxe says, you should move the layer's anchor point to 1,.5 before doing this animation, so it rotates around the right edge.

Here is some code from our "Kevin & Kell" cartoon app, that does an animation of a door swinging open on it's hinge:

//Open the door.
rotateAnimation = [CABasicAnimation animation];
rotateAnimation.keyPath = @"transform";
rotateAnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];

//Pivot on the right edge (y axis rotation)
theTransform = CATransform3DIdentity;
  theTransform.m34 = -1/100.0;
  theTransform = CATransform3DRotate(theTransform, degreesToRadians(70), 0, 1, 0);


rotateAnimation.toValue = [NSValue valueWithCATransform3D:theTransform];

rotateAnimation.duration = 0.5;

// leaves presentation layer in final state; preventing snap-back to original state
rotateAnimation.removedOnCompletion = NO;
rotateAnimation.fillMode = kCAFillModeBoth; 

rotateAnimation.repeatCount = 0;
rotateAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
rotateAnimation.delegate = self;
[treeDoorImageView.layer addAnimation:rotateAnimation forKey:@"transform"];

The transform logic is all but identical to yours (I use an m34 value of -1/100 for a more exaggerated 3D effect. Your -1/500 setting is more normal.)

Note that instead of trying to do the animation from a UIView animation block, I create a CABasicAnimation, and set it's fromValue and toValue properties to the starting and ending transform values.

You should be able to use this code as a starting-point for your animation.

0
Tricertops On

You need to use CAAnimation, not UIView block animation.

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
animation.duration = 2;
animation.fromValue = [NSValue valueWithCATransform3D:view.layer.transform]; // From the existing transform.
animation.toValue = [NSValue valueWithCATransform3D:transform]; // To the new one.

view.layer.transform = transform; // Set the new transform.
[view.layer addAnimation:animation forKey:@"door"]; // Animate visual change.

Also, as axte pointed out, you will have to set anchorPoint of the layer to (1, 0.5) to apply rotation around right edge of the layer.