The following code is used for a NSButton with wantsLayer
set to YES. This works, however if the app is busy processing something in the background, the rotation animation is very choppy:
POPSpringAnimation *animation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerRotation];
animation.springBounciness = 8;
animation.springSpeed = 10;
animation.toValue = @(M_PI);
[self.myButton.layer pop_addAnimation:animation forKey:@"rotate"];
I then changed it to the following and it works very smoothly:
CGAffineTransform transform = CGAffineTransformMakeRotation(-M_PI);
CABasicAnimation *thAnimation = [ CABasicAnimation animationWithKeyPath: @"transform" ];
thAnimation.duration = 0.2;
CATransform3D oldTrans = [self.myButton layer].transform;
thAnimation.fromValue = [ NSValue valueWithCATransform3D: oldTrans ];
CATransform3D newTrans = CATransform3DMakeAffineTransform (transform);
thAnimation.toValue = [ NSValue valueWithCATransform3D: newTrans ];
[[self.myButton layer] addAnimation: thAnimation forKey: @"rotate" ];
[[self.myButton layer] setAffineTransform: transform];
I'd like to however still use the POPSpringAnimation instead. I notice it directly uses a DisplayLink timer under the hood. Is there a way to make POP animate my affine transform instead?
Okay I've found the problem. In POPAnimator.m the displaylinkCallback
method is doing this:
dispatch_async(dispatch_get_main_queue(), ^{
[(__bridge POPAnimator*)context render];
});
Since it's rendering on the main thread, and the main thread of the app is at times busy or blocked, the animation blocks too. All I have to do is enable background thread on POP:
[POPAnimator setDisableBackgroundThread: NO];