#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