3

I'm trying to animate the rotation of an NSView around its center, but it keeps shifting side to side during rotation. What is causing this?

-(void)startRefreshAnimation {

    [NSAnimationContext beginGrouping];
    [[NSAnimationContext currentContext] setDuration:1.0];
    [[NSAnimationContext currentContext] setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
    [NSAnimationContext currentContext].completionHandler = ^{ [self startRefreshAnimation]; };
    [[view animator] setFrameCenterRotation:previousRotation - 90.0];
    previousRotation += -90.0;
    [NSAnimationContext endGrouping];

}

Shift up during rotation:

enter image description here

Shift down during rotation:

enter image description here

Jack Humphries
  • 13,056
  • 14
  • 84
  • 125

2 Answers2

2

here is the dummy project and the answer that I found. (For Cocoa Applicaiton)

Rotate NSImageView

github project (download)

Community
  • 1
  • 1
Vikas Bansal
  • 10,662
  • 14
  • 58
  • 100
1

From the documentation:

If the application has altered the layer’s anchorPoint property, the behavior is undefined. Sending this message to a view that is not managing a Core Animation layer causes an exception.

https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSView_Class/Reference/NSView.html

Is your view managing a CALayer with an unmodified anchor point?

EDIT

I setup similar code at got the exact same results. No adjust of origin or anchor point could resolve this problem. My theory is that this particular method contains bugs (does for autolayout), or works in a way which we don't anticipate. I achieved the correct effect using CABasicAnimation.

/* setup */

....
     _view.layer.anchorPoint = CGPointMake(0.5f, 0.5f);
     _view.layer.position = ...

    [self startRefreshAnimation];
}

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
    [self startRefreshAnimation];
}

-(void)startRefreshAnimation {

    CABasicAnimation *anim2 = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
    anim2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    anim2.fromValue = [NSNumber numberWithFloat:previousRotation * (M_PI / 180.0f)];
    anim2.toValue = [NSNumber numberWithFloat:(previousRotation + 90.0f) * (M_PI / 180.0f)];
    previousRotation = previousRotation + 90.0f;
    anim2.duration = 1.0f;
    anim2.delegate = self;
    [_view.layer addAnimation:anim forKey:@"transform"];
}
Justin Meiners
  • 10,754
  • 6
  • 50
  • 92
  • I'm creating and managing a `CALayer` on my view (to set the background color to purple), but I'm not modifying the anchor point. See my edit to view the code affecting the `CALayer.` – Jack Humphries Jul 11 '13 at 15:15
  • @JackHumphries Im curious, doesnt the second layer overwrite the first makeBackingLayer? – Justin Meiners Jul 11 '13 at 15:23
  • I didn't notice. I just copied and pasted the code from online without interpreting it. – Jack Humphries Jul 11 '13 at 15:40
  • When I call `setFrameCenterRotation` on `view` instead of `[view animator]`, it works, but the rotation is instant. There is no animation. – Jack Humphries Jul 11 '13 at 15:48
  • @JackHumphries hmm - I am setting up a test on my comp ill let you know – Justin Meiners Jul 11 '13 at 15:50
  • @JackHumphries alright I have mine working just like yours and I think I know the problem. It rotates around the corner - but that corner position changes every rotation cycle. This makes it look like it's close even though it's way off. – Justin Meiners Jul 11 '13 at 16:05
  • This works better, though it rotates by the bottom left corner, instead of around the center. Do you know how to fix this? I did set the anchor point to (0.5f, 0.5f). – Jack Humphries Jul 11 '13 at 17:49
  • @JackHumphries hmm I set the frame before I set the anchorPoint and position, I wonder if that has something to do with it... – Justin Meiners Jul 11 '13 at 17:53
  • 1
    Justin's answer works because it adjusts the layer's transform. Apple does strange things with the anchorPoint when using `setFrameCenterRotation`, even if you set the anchorPoint. This was my experience and Isaac Chen provides an excellent write-up: https://isaacxen.github.io/2017/12/21/rotating-a-view-is-not-easy/ – InfalibleCoinage Mar 09 '19 at 05:58