Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Core Animation: set anchorPoint on 10.8 to rotate a layer about its center

NB: This is for a Cocoa app on OS X, NOT iOS.

I have a layer-backed NSButton (subclass of NSView). What I want to do is rotate that button using Core Animation. I'm using the following code to do it:

CABasicAnimation *a = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
a.fromValue = [NSNumber numberWithFloat:0];
a.toValue = [NSNumber numberWithFloat:-M_PI*2];
[_refreshButton.layer setAnchorPoint:CGPointMake(0.5, 0.5)];
a.duration = 1.8; // seconds
a.repeatCount = HUGE_VAL;
[_refreshButton.layer addAnimation:a forKey:nil];

This works, EXCEPT that when it runs, the layer jumps down and to the left so that its center point is at the origin point of the NSView, which is the lower-left corner at (0,0). The layer then rotates about its center, but obviously the jumping-to-the-lower-left-corner is not acceptable.

So, after much reading, I found this line in the 10.8 API release notes:

On 10.8, AppKit will control the following properties on a CALayer 
(both when "layer-hosted" or "layer-backed"): geometryFlipped, bounds, 
frame (implied), position, anchorPoint, transform, shadow*, hidden, 
filters, and compositingFilter. Use the appropriate NSView cover methods 
to change these properties.

This means that AppKit is "ignoring" my call to -setAnchorPoint in the code above and, instead, is setting that anchor point to the NSView's origin (0,0).

My question is: how do I solve this? What is the "appropriate NSView cover method" to set the anchorPoint for the layer (I can't find such a method on NSView). At the end of the day, I just want my button to rotate around its center point, indefinitely.

like image 991
Bryan Avatar asked Feb 12 '13 18:02

Bryan


1 Answers

I don't see any methods on NSView that are a direct “cover” for anchorPoint.

What I do see in the 10.8 release notes, besides what you quoted, is this:

The anchorPoint is also always set to be (0,0), …

The anchorPoint controls which point of the layer is at position in the superlayer's coordinate system. NSView sets self.layer.anchorPoint to (0,0), which means the layer's lower-left corner is at self.layer.position.

When you set anchorPoint to (0.5,0.5), that means the center of the layer should be at the layer's position. Since you didn't modify position, this has the effect of moving the layer down and to the left, as you are seeing.

You need to compute the position you want the layer to have when its anchorPoint is (0.5,0.5), like this:

CGRect frame = _refreshButton.layer.frame;
CGPoint center = CGPointMake(CGRectGetMidX(frame), CGRectGetMidY(frame));
_refreshButton.layer.position = center;
_refreshButton.layer.anchorPoint = CGPointMake(0.5, 0.5);
like image 56
rob mayoff Avatar answered Oct 16 '22 06:10

rob mayoff