Search code examples
nsviewanimation

Using NSViewAnimation to continuously animate frameRotation


I'm trying to figure out the right way to continuously animate the frameRotation of a layer-backed NSView.

In particular, I'm basically trying to re-create how the new Launchpad animates when you click and hold an icon. The event handling isn't the problem, it's the actual repeating animation.

So far, I've used NSTimer to animate the frameRotation back and forth using the view's animator proxy. While this works, it seems to be resource intensive and I'm sure NSAnimation could be used for this.

I'm just wondering if someone can point me in the right direction here.

EDIT: This doc here: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/AnimationGuide/Articles/ViewAnimations.html#//apple_ref/doc/uid/TP40003593-DontLinkElementID_7

only discusses the view's frame rect and alpha value. So I'm not sure how to use this for frameRotation

Kind regards, Alec


Solution

  • Simple answer is you can't with NSViewAnimation, but you can with CABasicAnimation.

    Here is what I came up with:

    Add this animation to the view's layer:

    - (CABasicAnimation *)rockingAnimation {
    
    float diff = 0.065 - .055;
    float startValue = (((float) (arc4random() % ((unsigned)RAND_MAX + 1)) / RAND_MAX) * diff) + 0.055;
    float endValue = (((float) (arc4random() % ((unsigned)RAND_MAX + 1)) / RAND_MAX) * diff) - 0.055;
    float duration = (((float) (arc4random() % ((unsigned)RAND_MAX + 1)) / RAND_MAX) * diff) + 0.085;
    
    CABasicAnimation *rockAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
    [rockAnimation setFromValue:[NSNumber numberWithFloat:startValue]];
    [rockAnimation setToValue:[NSNumber numberWithFloat:endValue]];
    [rockAnimation setDuration:duration];
    [rockAnimation setRemovedOnCompletion:YES];
    [rockAnimation setFillMode:kCAFillModeForwards];
    [rockAnimation setAutoreverses:YES];
    [rockAnimation setRepeatCount:10000];
    
    return rockAnimation;
    

    }

    This gets a pretty good result.