Cocoa Is My Girlfriend

Taglines are for Windows programmers

Core Animation Tutorial: Window Shake Effect

Core Animation is really the buzz among Cocoa developers these days and we are no different from the rest. Learning to do simple fades and frame movement is trivial, but figuring out the more complex effects is quite a challenge. We decided to venture out and try to create some really concise examples of effects you might find used in Leopard. And while these effects may not be done with Core Animation where they are found in the OS, we’ve set out to duplicate them in Core Animation regardless. Our first challenge? Shaking a login window.

Just Say No Window

Shaking To Say No

If you have your system set up to auto-login, you’ve probably never seen this effect before. Simply put, when you enter your password in the login window when doing a manual login, if you fat-finger it, it will shake you off–which is to say it will shake side to side several times in succession. It’s really quite a clever and intuitive response to what is normally responded to with a dialog.

OS X Login

After a fair bit of research and tweaking some code we found in a CocoaBuilder post written by Bill Dudney, author of the upcoming Core Animation for OS X: Creating Dynamic Compelling User Interfaces, we came up with a very elegant and tight solution. We have provided an example project you can download, but here is the frame animation code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- (CAKeyframeAnimation *)shakeAnimation:(NSRect)frame
{
    CAKeyframeAnimation *shakeAnimation = [CAKeyframeAnimation animation];
 
    CGMutablePathRef shakePath = CGPathCreateMutable();
    CGPathMoveToPoint(shakePath, NULL, NSMinX(frame), NSMinY(frame));
    int index;
    for (index = 0; index < numberOfShakes; ++index)
    {
        CGPathAddLineToPoint(shakePath, NULL, NSMinX(frame) - frame.size.width * vigourOfShake, NSMinY(frame));
        CGPathAddLineToPoint(shakePath, NULL, NSMinX(frame) + frame.size.width * vigourOfShake, NSMinY(frame));
    }
    CGPathCloseSubpath(shakePath);
    shakeAnimation.path = shakePath;
    shakeAnimation.duration = durationOfShake;
    return shakeAnimation;
}

That’s really all there is to it. We’ve set some static variables in the demo project that are used to determine how many times to shake the window, how vigorously to shake it and how long the shake effect should take to complete. Play with these variables yourself to see a variation of this same shaking effect you find in the OS X login window.



8 Comments so far

  1. nedaf7 February 27th, 2008 3:23 pm

    Thanks, this effect should prove itself useful. Here are the static variable values I thought worked best:
    static int numberOfShakes = 4;
    static float durationOfShake = .5f;
    static float vigourOfShake = 0.05f;

  2. News » Window Shake Effect via Core Animation February 27th, 2008 8:12 pm

    [...] Cocoa Is My Girlfriend: “We decided to venture out and try to create some really concise examples of effects you might find used in Leopard. And while these effects may not be done with Core Animation where they are found in the OS, we’ve set out to duplicate them in Core Animation regardless. Our first challenge? Shaking a login window.” [...]

  3. robsoft February 28th, 2008 7:56 am

    I love this touch myself - I put something similar into a Windows app of mine that’s just doing a beta round with the client. The feedback regarding the login and change password dialogs was really positive, including ‘we love the wiggling it does when you get it wrong. It’s great that you don’t need to have an extra dialog and button to acknowledge you know you made a mistake.

    Unfortunately, my Windows/Delphi/VCL wiggle hack isn’t as smooth (or as short) as the Mac/Cocoa/Core Animation version. :-(

  4. [...] is short, but it has an XCode project that you can download and use. Take a look at the post, Core Animation Tutorial: Window Shake Effect and let me know what you [...]

  5. David Casseres February 29th, 2008 6:18 pm

    One detail bothers me. You create a dictionary entry with the CAKeyframeAnimation object returned by [self shakeAnimation:[window frame]] and the key @”frameOrigin”. That seems to imply that NSWindow has a property or ivar called frameOrigin, but nothing in the headers or documentation identifies it. How do you know what keys you can use for CAKeyframeAnimation objects?

  6. Marcus Zarra March 2nd, 2008 1:07 pm

    David,

    Take a look at the docs again for NSWindow and you will find the method:

    - (void)setFrameOrigin:(NSPoint)point

    That is the method that Matt is kicking in his example. You are right that there is no getter for it in the documentation but for this example one is not needed. In fact, this example could have piggy-backed off any number of properties on the NSWindow and achieved the same effect.

  7. [...] Cocoa Is My Girlfriend: “We decided to venture out and try to create some really concise examples of effects you might find used in Leopard. And while these effects may not be done with Core Animation where they are found in the OS, we’ve set out to duplicate them in Core Animation regardless. Our first challenge? Shaking a login window.” Comments RSS | Trackback URL [...]

  8. [...] you see in OS X itself that present an interesting challenge to duplicate. In a previous post, we demonstrated how to shake a login window similar to the way that OS X shakes the login window when the user enters the wrong password. This [...]

Leave a reply

You must be logged in to post a comment.

Watch the latest videos on YouTube.com