Cocoa中可以通过NSAnimation可以实现自定义动画。NSAnimation本身并没有任何的操作UI的能力,但是它能够提供类似NSTimer的定时功能,不过更加强大,通过设置progress mark可以设置多个触发点。对于需要平滑动作的,更是可以通过继承NSAnimation,在重写一些方法后能提供精确到帧的动画。需要注意的是,NSAnimation默认的动画执行模式为阻塞执行,需要等待动画执行完才会返回,可以通过setAnimationBlockingMode:进行设置。
1. 通过代理获取触发点,执行动画操作。跳跃性执行,需要设置较多的触发点。
1 - (IBAction)didAnimateClicked:(id)sender { 2 //创建时长为5s的动画并设置时间曲线 3 NSAnimation *animation = [[NSAnimation alloc] initWithDuration:5 animationCurve:NSAnimationEaseIn]; 4 //设置代理 5 [animation setDelegate:self]; 6 //设置关键点 7 [animation setProgressMarks:@[@0.1, @0.2, @0.5, @1.0]]; 8 //设置阻塞模式,默认为阻塞 9 [animation setAnimationBlockingMode:NSAnimationNonblocking]; 10 //开始执行动画 11 [animation startAnimation]; 12 }
需要通过设置代理来获取时间点进行操作。
1 - (void)animationDidEnd:(NSAnimation *)animation { 2 NSLog(@"animation ended!"); 3 } 4 5 - (void)animationDidStop:(NSAnimation *)animation { 6 NSLog(@"animation stopped"); 7 } 8 9 //关键点代理方法 10 - (void)animation:(NSAnimation *)animation didReachProgressMark:(NSAnimationProgress)progress 11 { 12 NSLog(@"progress: %f", progress); 13 14 NSRect winRect = [[NSApp mainWindow] frame]; 15 NSRect screenRect = [[NSScreen mainScreen] visibleFrame]; 16 winRect.origin.x = progress * (screenRect.size.width - winRect.size.width); 17 [[NSApp mainWindow] setFrame:winRect display:YES]; 18 }
2. 通过继承NSAnimation执行动画操作。(流畅动画)
1 //自定义动画类 2 - (IBAction)didCustomAnimateClicked:(id)sender { 3 YGYCustomAnimation *animation = [[YGYCustomAnimation alloc] initWithDuration:5 animationCurve:NSAnimationEaseIn]; 4 [animation setAnimationBlockingMode:NSAnimationNonblocking]; 5 [animation startAnimation]; 6 }
直接重写函数:
1 #import <Cocoa/Cocoa.h> 2 3 @interface YGYCustomAnimation : NSAnimation 4 5 @end
1 #import "YGYCustomAnimation.h" 2 3 @implementation YGYCustomAnimation 4 5 //自定义动画类必须实现的方法 6 - (void)setCurrentProgress:(NSAnimationProgress)progress 7 { 8 //必须调用super 9 [super setCurrentProgress:progress]; 10 11 //窗口从左平滑右移 12 NSRect winRect = [[NSApp mainWindow] frame]; 13 NSRect screenRect = [[NSScreen mainScreen] visibleFrame]; 14 winRect.origin.x = progress * (screenRect.size.width - winRect.size.width); 15 [[NSApp mainWindow] setFrame:winRect display:YES]; 16 } 17 18 @end
更多信息:长沙戴维营教育