33

How do I rotate a CALayer 90 degrees? I need to rotate everything include sublayers and the coordinate system.

Kristina
  • 15,859
  • 29
  • 111
  • 181
  • Don't forget to set layer's anchor point if needed. It won't "flip" the same way if you place it on the middle instead of the top of your layer – mrcendre May 27 '13 at 13:01

5 Answers5

60

Obj-C:

theLayer.transform = CATransform3DMakeRotation(90.0 / 180.0 * M_PI, 0.0, 0.0, 1.0);

Swift:

theLayer.transform = CATransform3DMakeRotation(90.0 / 180.0 * .pi, 0.0, 0.0, 1.0)

That is, transform the layer such that it is rotated by 90 degrees (π / 2 radians), with 100% of that rotation taking place around the z-axis.

Abhi Beckert
  • 32,787
  • 12
  • 83
  • 110
Jonathan Grynspan
  • 43,286
  • 8
  • 74
  • 104
  • 1
    M_PI is Double and CATransform3DMakeRotation requires angle to be CGFloat, so CGFloat(M_PI) should be used instead – Mina Kolta Aug 04 '15 at 15:26
  • In C, the conversion from double to CGFloat is implicit (and casts in C and Objective-C take the form *(T)expression*, not *T(expression)*. Are you thinking of Swift or C++?) Moreso, `M_PI` is multiplied by a `double` in the statement above, so it's widened, defeating the purpose of the cast. – Jonathan Grynspan Aug 05 '15 at 00:12
  • how to make it rotate using the center as the anchor point? Its rotation the whole layer – apinho Jul 18 '16 at 13:24
  • M_PI causes casting issues in Swift and has been deprecated in favour of `Type.pi` or just `.pi` which will use the correct type (in this case, `CGFloat.pi`). – Abhi Beckert Feb 10 '18 at 05:00
  • @apinho set `.anchor` to the center of the frame – Fattie Aug 07 '19 at 19:46
  • Make sure you set the frame of "theLayer" AFTER you rotate it. – Mason Ballowe Jan 14 '22 at 16:27
13

If I'm animating it I use something like this in my apps:

- (NSObject *) defineZRotation {
    // Define rotation on z axis
    float degreesVariance = 90;
    // object will always take shortest path, so that
    // a rotation of less than 180 deg will move clockwise, and more than will move counterclockwise
    float radiansToRotate = DegreesToRadians( degreesVariance );
    CATransform3D zRotation;
    zRotation = CATransform3DMakeRotation(radiansToRotate, 0, 0, 1.0);  
    // create an animation to hold "zRotation" transform
    CABasicAnimation *animateZRotation;
    animateZRotation = [CABasicAnimation animationWithKeyPath:@"transform"];
    // Assign "zRotation" to animation
    animateZRotation.toValue = [NSValue valueWithCATransform3D:zRotation];
    // Duration, repeat count, etc
    animateZRotation.duration = 1.5;//change this depending on your animation needs
    // Here set cumulative, repeatCount, kCAFillMode, and others found in
    // the CABasicAnimation Class Reference.
    return animateZRotation;
}

Of course you can use it anywhere, don;t have to return it from a method if that doesn;t suit your needs.

Rab
  • 2,806
  • 2
  • 16
  • 20
  • No need to create a CAAnimation object for rotating a view. For that, animateWithDuration:animations works just fine. See my answer for more details. – Duncan C May 17 '12 at 18:48
  • @Duncan I believe this method only applies to UIView, not CALayer. See my response to your answer. – Rab May 18 '12 at 14:33
8

Basically something like that:

CGAffineTransform rotateTransform = CGAffineTransformMakeRotation(M_PI / 2.0); [myCALayer setAffineTransform:rotateTransform];

EDIT: It'll rotate clockwise or counter-clockwise depending on the platform (iOS or Mac OS).

fabian789
  • 8,348
  • 4
  • 45
  • 91
SteamTrout
  • 1,684
  • 1
  • 13
  • 9
1

To rotate 90' right:

myView.transform = CGAffineTransformMakeRotation(M_PI_2);
Sam Soffes
  • 14,831
  • 9
  • 76
  • 80
Chris
  • 39,719
  • 45
  • 189
  • 235
0

Rab showed how do do it with a CAAnimation object. Its actually simpler than that:

[myView animateWithDuration: 0.25 
  animations:
  ^{
     myView.transform = CGAffineTransformMakeRotation(M_PI/2);
   }
];

(lifting the transform line from Chris's answer - too lazy to rewrite it since he already provided the perfect code.)

Chris's code would rotate the view without animation. My code above will do the same thing with animation.

By default, animations use ease in, ease out timing. You can change that with a slightly more complex version of the animateWithDuration call (Use animateWithDuration:delay:options:animations:completion: instead, and pass in a the desired timing in the options parameter.)

Arun
  • 3,406
  • 4
  • 30
  • 55
Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • animateWithDuration:animations: is a block-based method for UIView. The question here is how to animate CALayer -- CALayer doesn't have this method, or at least it's not documented as having it. Also in 2010 the method animateWithDuration:animations: didn't exist yet (nor, I think, did anything block-based in Obj-C)... so this would be more of an "update for 2012" if it did apply. – Rab May 18 '12 at 14:30
  • also chris' code will animate. with the standard duration of CALayer animations. – vikingosegundo Jan 13 '13 at 17:37
  • Fair points that block-based animations probably didn't exist in 2010, and that this question specifically asked about CALayer, not view, animation. UIView animations end up generating CAAnimations under the covers, but you can only use a UIView animation if the layer you want to animate is a view's backing layer. – Duncan C Jun 02 '19 at 20:01
  • @vikingosegundo, like mine, Chris's code changes the view's transform, not the layer's. I'm pretty sure that changing view properties doesn't create an implicit animation like changing animatable layer properties does. (This is an OLD thread but somebody just down-voted my answer, which prompted me to revisit it.) – Duncan C Jun 02 '19 at 20:04