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.
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With