老谭笔记

OSX的动画实现(一)——动画的几种实现方式

不久前,在公司的一个内部交流会上我给同事们整理和分享了OSX上实现动画的一个专项课题,所以就一直都想把PPT的内容和一些示例代码也整理到博客上面,今天终于下定决心,把这件事情给完成,希望它能是有价值的!


  • 动画提升用户的体验性


优秀的软件总是会在界面的设计、用户操作后的影响、视图的切换等多个方面利用炫丽的动画让你眼前一亮。

animation_1


  • cocoa实现动画的几种方式


animation_2


  • 通过NSViewAnimation实现的动画


NSViewAnimation是AppKit提供的动画类,主要适用的对象为NSView和NSWindow,它所能定制的动画属性也只限于Frame的改变,和渐显渐稳,但因为它使用非常方便,一般在项目中也会经常使用到。

animation_3

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
NSRect startFrame = [self.view frame];
NSRect endFrame = NSMakeRect(0, 0, startFrame.size.width, startFrame.size.height);
NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys:
self.view,NSViewAnimationTargetKey,
NSViewAnimationFadeInEffect,NSViewAnimationEffectKey,
[NSValue valueWithRect:startFrame],NSViewAnimationStartFrameKey,
[NSValue valueWithRect:endFrame],NSViewAnimationEndFrameKey, nil];
NSViewAnimation *animation = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dictionary]];
animation.delegate = self;
animation.duration = 2;
//NSAnimationBlocking阻塞
//NSAnimationNonblocking异步不阻塞
//NSAnimationNonblockingThreaded线程不阻塞
[animation setAnimationBlockingMode:NSAnimationNonblockingThreaded];
[animation startAnimation];

示例代码下载:McAnimation_NSViewAnimation


  • 使用NSAnimationContext实现的动画


NSAnimationContext是AppKit提供的另一种较为高级的动画类,可以通过设置NSView或NSWindow的一些属性来设置动画,并不是所有的属性都能用来做动画,只有与显示有关联的部分属性支持,如果你需要定义更多的属性支持动画,就需要你重写一些方法了,此处暂不做讨论。

示例代码:

1
2
3
4
5
6
7
8
9
[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
[context setDuration:2.0];
float rotation = animationView.frameRotation;
[[animationView animator] setFrameOrigin:NSZeroPoint];
[[animationView animator] setAlphaValue:0.0];
//[[animationView animator] setFrameRotation:rotation+360];
} completionHandler:^{
NSLog(@"All done!");
}];

示例代码下载:McAnimation_NSAnimationContext


  • 通过QuartzCore实现的动画


QuartzCore框架如同在iOS的表现一样,提供了非常丰富的动画显示,这也是整个Cococa体系中专为动画而生的框架,几乎大多数的AppKit的动画类的最终也是由QuartzCore来实现的,QuartzCore中包括了CAAnimation及其子类CABaseAnimation,CAKeyframeAnimation,CAAnimationGroup等等,甚至你也可以继承于CAAnimation实现你自己的动画类,CAAnimation的表现是CALayer是分不开的,以下是是关于CALayer显示密切联系的一些属性及其含义:

animation_4

animation_5

animation_6

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//透明度
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
animation.duration = 2.0;
animation.autoreverses = YES;
animation.repeatCount = NSIntegerMax;
animation.fromValue = [NSNumber numberWithFloat:1];
animation.toValue = [NSNumber numberWithFloat:0];
[animationView.layer addAnimation:animation forKey:@""];
//缩放1
// CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
// animation.duration = 2.0;
// animation.autoreverses = YES;
// animation.repeatCount = NSIntegerMax;
// animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
// animation.toValue = [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DIdentity, 1, 1, 0.1)];
// [animationView.layer addAnimation:animation forKey:@""];
//缩放2
// CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
// animation.duration = 2.0;
// animation.autoreverses = YES;
// animation.repeatCount = NSIntegerMax;
// animation.fromValue = [NSNumber numberWithFloat:1.0];
// animation.toValue = [NSNumber numberWithFloat:0.1];
// [animationView.layer addAnimation:animation forKey:@""];
//旋转1
// CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
// animation.duration = 2.0;
// //animation.autoreverses = YES;
// animation.repeatCount = NSIntegerMax;
// animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
// animation.toValue = [NSValue valueWithCATransform3D:CATransform3DRotate(CATransform3DIdentity, pi, 0, 0, 1)];
// [animationView.layer addAnimation:animation forKey:@""];
//旋转2
// CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.x"];
// animation.duration = 2.0;
// //animation.autoreverses = YES;
// animation.repeatCount = NSIntegerMax;
// animation.fromValue = [NSNumber numberWithFloat:0];
// animation.toValue = [NSNumber numberWithFloat:2*pi];
// [animationView.layer addAnimation:animation forKey:@""];
//平移1
// CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
// animation.duration = 2.0;
// animation.autoreverses = YES;
// animation.repeatCount = NSIntegerMax;
// animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
// animation.toValue = [NSValue valueWithCATransform3D:CATransform3DTranslate(CATransform3DIdentity, 100, 100, 0)];
// [animationView.layer addAnimation:animation forKey:@""];

示例代码下载(CABaseAnimation):McAnimation_CABaseAnimation

示例代码下载(CAKeyframeAnimation):McAnimation_CAKeyframeAnimation

示例代码下载(CAAnimationGroup):McAnimation_CAAnimationGroup