#import <Cocoa/Cocoa.h>#import <QuartzCore/QuartzCore.h>@interface KeyFrameView : NSView{ NSImageView *mover; NSImageView *girl; CGMutablePathRef heartPath;}- (CGPathRef)heartPath;- (CAKeyframeAnimation *)originAnimation;- (CABasicAnimation *)basicAnimation;//For NSView property animation 根据NSView的属性(frameOrigin, frameSize)等生成动画- (CABasicAnimation *)frameAnimation;//For path animation 根据CGPath生成动画- (CAAnimationGroup *)groupAnimation;//For group animations 组合多外animation- (CATransition *)transition;//For NSView transition 内置了一些动画,如淡入/淡出, 移动等- (void)addBounceAnimation;- (void)bounce;- (CAMediaTimingFunction *)getTimingFunction;@end
//// KeyFrameView.m// KeyFrameAnimationTest//// Created by Peng Leon on 12/11/9.// Copyright (c) 2012年 __MyCompanyName__. All rights reserved.//#import "KeyFrameView.h"@implementation KeyFrameView- (id)initWithFrame:(NSRect)frame{ self = [super initWithFrame:frame]; if (self) { // Initialization code here. CGFloat xInset = 3.0f * (NSWidth(frame) / 8.0f); CGFloat yInset = 3.0f * (NSHeight(frame) / 8.0f); NSRect moverFrame = NSInsetRect(frame, xInset, yInset); mover = [[NSImageView alloc] initWithFrame:moverFrame]; [mover setImageScaling:NSScaleToFit]; [mover setImage:[NSImage imageNamed:@"IMG_1001.JPG" ]]; [mover setWantsLayer:YES]; [self addSubview:mover]; girl = [[NSImageView alloc] initWithFrame:moverFrame]; [girl setImageScaling:NSScaleToFit]; [girl setImage:[NSImage imageNamed:@"IMG_2116.JPG"]]; [girl setWantsLayer:YES]; [self setWantsLayer:YES]; [self addBounceAnimation]; } return self;}- (void)drawRect:(NSRect)dirtyRect{ // Drawing code here.}- (BOOL)acceptsFirstResponder{ return YES;}- (void)mouseDown:(NSEvent *)theEvent{ [self bounce];}- (void)bounce{ //NSRect rect = [mover frame]; //[[mover animator] setFrameOrigin:rect.origin]; //[[mover animator] setAlphaValue:[mover alphaValue]]; if (nil != [mover superview]) { [[self animator] replaceSubview:mover with:girl]; }else{ [[self animator] replaceSubview:girl with:mover]; }}- (void)addBounceAnimation{ //[mover setAnimations:[NSDictionary dictionaryWithObjectsAndKeys:[self originAnimation], @"frameOrigin", nil]]; //[mover setAnimations:[NSDictionary dictionaryWithObjectsAndKeys:[self basicAnimation], @"alphaValue", nil]]; //[mover setAnimations:[NSDictionary dictionaryWithObjectsAndKeys:[self groupAnimation], @"alphaValue", nil]]; self.animations = [NSDictionary dictionaryWithObject:[self transition] forKey:@"subviews"];}- (CAMediaTimingFunction *)getTimingFunction{ CGFloat c1x = 0.0; CGFloat c1y = 0.0; CGFloat c2x = 0.5; CGFloat c2y = 1.0; return [[CAMediaTimingFunction alloc] initWithControlPoints:c1x :c1y :c2x :c2y]; //return [CAMediaTimingFunction functionWithName:@"easeIn"];}- (CATransition *)transition{ CATransition *transtion = [CATransition animation]; //transtion.type = kCATransitionFade;//淡入淡出 transtion.type = kCATransitionPush;//push View //transtion.type = kCATransitionMoveIn; //transtion.type = kCATransitionReveal;//move //transtion.subtype = kCATransitionFromTop; transtion.timingFunction = [self getTimingFunction]; transtion.duration = 2.0f; transtion.delegate = self; return transtion;}- (CAAnimationGroup *)groupAnimation{ CAAnimationGroup *groupAnimation = [CAAnimationGroup animation]; groupAnimation.animations = [NSArray arrayWithObjects:[self basicAnimation], [self originAnimation], nil]; groupAnimation.duration = 1.0f; groupAnimation.autoreverses = YES; return groupAnimation;}- (CABasicAnimation *)basicAnimation{ CABasicAnimation *animation = [CABasicAnimation animation]; animation.keyPath = @"alphaValue"; animation.fromValue = [NSNumber numberWithFloat:0.0]; animation.toValue = [NSNumber numberWithFloat:1.0]; animation.duration = 3.0; animation.delegate = self; return animation;}- (CAKeyframeAnimation *)originAnimation{ CAKeyframeAnimation *animation = [CAKeyframeAnimation animation]; animation.keyPath = @"frameOrigin"; animation.path = [self heartPath];//设置keyFrame的path animation.duration = 3.0f;//动画持续的时间(秒) animation.calculationMode = kCAAnimationCubic; return animation;}- (CABasicAnimation *)frameAnimation{ CABasicAnimation *animation = [CABasicAnimation animation]; animation.fromValue = [NSNumber numberWithFloat:0.0]; animation.toValue = [NSNumber numberWithFloat:1.0]; animation.duration = 2.0; animation.delegate = self; return animation;}- (CGPathRef)heartPath{ NSRect frame = [mover frame]; if (heartPath == NULL) { heartPath = CGPathCreateMutable(); CGPathMoveToPoint(heartPath, NULL, NSMinX(frame), NSMinY(frame)); CGPathAddLineToPoint(heartPath, NULL, NSMinX(frame) - NSWidth(frame), NSMinY(frame) + NSHeight(frame) * 0.85); CGPathAddLineToPoint(heartPath, NULL, NSMinX(frame), NSMinY(frame) - NSHeight(frame) * 1.5); CGPathAddLineToPoint(heartPath, NULL, NSMinX(frame) + NSWidth(frame), NSMinY(frame) + NSHeight(frame) * 0.85); CGPathAddLineToPoint(heartPath, NULL, NSMinX(frame), NSMinY(frame)); CGPathCloseSubpath(heartPath); } return heartPath;}#pragma mark -#pragma mark CAAnimation Delegate- (void)animationDidStart:(CAAnimation *)theAnimation{ NSLog(@"call animationDidStart: function.");}- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag{ NSLog(@"call animationDidStop:finished: function."); //[mover setAlphaValue:1.0];}@end