Rotating a UIView in 3D

OSCON 2013 Speaker Series


Jon Manning (@desplesda) and Paris Buttfield-Addison (@parisba) are co-founders of Secret Lab and authors of the forthcoming Learning Cocoa with Objective-C, 3rd Edition. They’ll be speaking at OSCON this week in Portland, OR. Here they explain how to rotate a UIView in 3D on iOS.


One of the simplest visual tricks you can do in iOS is to make a part of your UI pretend to be a 3D object. We’ve found that this is an excellent way to add some life and visual interest to both apps and games.

Below, you’ll learn how to make a view rotate in 3D and have a perspective effect.

phone

First, your project needs to use the QuartzCore framework.

Next, when you want the animation to begin, you do this:

CABasicAnimation* animation = [CABasicAnimation
animation WithKeyPath:@"transform.rotation.y"];
animation.fromValue = @(0);
animation.toValue = @(2 * M_PI);
animation.repeatCount = INFINITY;
animation.duration = 5.0;

[self.rotatingView.layer addAnimation:animation forKey:@"rotation"];

CATransform3D transform = CATransform3DIdentity;
transform.m34 = 1.0 / 500.0;
self.rotatingView.layer.transform = transform;

To stop the animation, you do this:

[self.rotatingView.layer removeAnimationForKey:@"rotation"];

How It Works

CABasicAnimation allows you to animate a property of a view from one value to another. In the case of rotating a view, the property that we want to animate is its rotation, and the values we want to animate from and to are angles.

When you create the animation using [CABasicAnimation animationWithKeyPath:], you specify the property you want to animate. In this case, the one we want is the rotation around the Y axis.

CABasicAnimation* animation = [CABasicAnimation
animationWithKeyPath:@"transform.rotation.y"];

The animation is then configured. In this example, we made the rotation start from zero, and proceed through to a full circle. In Core Animation, angles are measured in radians, and there are 2 * π radians in a full circle. So, the from value and to value are set thusly:

animation.fromValue = @(0);
animation.toValue = @(2 * M_PI);

Next, the animation is told that it should repeat an infinite number of times, and that the full rotation should take 5 seconds.

animation.repeatCount = INFINITY;
animation.duration = 5.0;

The animation is started by adding the animation to the view’s layer, using the addAnimation:forKey: method. This method takes two parameters: the animation object that you want to use, and a key (or name) that the animation should be referred by.

Don’t be confused by the similarity between the “key” that you use when you add the animation, and the “key path” you use when creating the animation. The former is just a name you give the animation, and can be anything; the “key path” describes exactly what the animation modifies.

[self.rotatingView.layer addAnimation:animation forKey:@"rotation"];

The last step to this is to give the rotating view a little perspective. If you run the code while omitting the last few lines, you’ll end up with a view that appears to horizontally squash and stretch. What you want is for the edge that’s approaching the user’s eye to appear to get bigger, while the edge that’s moving away from the user’s eye to get smaller.

This is done by modifying the view’s 3D transform. By default, all views have a transform matrix applied to them that makes them all lie flat over each other. When you want something to have perspective, though, this doesn’t apply, and we need to override it.

CATransform3D transform = CATransform3DIdentity;
transform.m34 = 1.0 / 500.0;
self.rotatingView.layer.transform = transform;

The key to this part of the code is the second line: the one where the m34 field of the transform is updated. This part of the transform controls the sharpness of the perspective. (It’s basically how much the z coordinate gets scaled towards or away from the vanishing point as it moves closer to or further from the “camera“.)

As you can see, adding 3D and perspective effects isn’t terribly difficult, but the results can provide an excellent payoff in terms of user immersion.

tags: , , ,