macoscocoacore-animationfacebook-pop

How to use Facebook Pop to animate layer affine transform?


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?


Solution

  • 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];