今天,Cocoachina会开始一个Core Animation的入门教学,和大家共同学习Core Animation的使用。本站介绍过不少Core Animation的文章,这篇文章是一个入门教学,从头帮助你了解Core Animation以及如何入门。
Core Animation是苹果在Leopard中加入的新API,主要用于利用显卡硬件制作动态的用户界面。同时,在iPhone SDK中也支持这种API。在Leopard和iPhone中,你会看到苹果大量使用这种很酷的效果,比如iTunes/iPhone的CoverFlow效果:
Core Animation的好处
Core Animation的最大好处是可以帮助Mac或者iPhone的开发者减少代码量。因为如果你想用Core Image或者Open GL实现界面的动画特效,其实也是可以的,主要是非常麻烦。而用Core Animation可以极大简化开发难度和减少代码量。
如果你想用Core Animation建立你自己独特的用户界面,首先强烈建议你有一点艺术感,单单会使用Core Animation不能让你成为艺术家。另外,你最好会用一点Adobe Photoshop或者Adobe Flash,在实现效果之前,先动手画一画,心里大致有个感觉。
本文不会涉及到太深的技术或是数学算法层面,作者本人在这方面非常不精通。本文只是简单地把你从苹果晦涩的技术文档中解救出来,看过这篇文章后你应该可以开始直接在程序里使用Core Animation了。
需要了解哪些
阅读本文之前,最好你已经有一点Cocoa开发的基础,本文不会详述细节。首先,你需要了解Objective-C,如果不了解,可以先看一下本站的新手文章:
另外你还要了解一点Objective-C 2.0的属性说得是什么。同时,你需要了解如何使用XCode,这是比较基本的。
开始
要在Cocoa程序中使用Core Animation,首先要在程序中引用Quartz.framework,另外在.h文件中需要包含
#import <Quartz/Quartz.h>
这样就可以使用了。
Core Animation绘图的基础是“层”,叫做CALayer。你可以在View中设置层,层中可以放置更多的层。每个层都可以设定单独的动作,还可以给上一级的层设置动作,下一级的层就可以跟着上一层进行动作。iPhone官方SDK同样支持CALayer,而在底层的Toolchain中,你需要用的类叫做LKLayer(Layer Kit),其实是一样的。
Core Animation动画的基础主要是CAAnimation和CATransition,CAAnimation主要用于设定层的动作,比如放大缩小旋转等等,而CATransition主要用于比如设置渐变、翻页、切换等一些比较特殊的特效。
Core Animation的动画是基于View的,最简单的用法是使用View的animator,修改一下View对象的属性,但是消息发给对象的animator即可。比如从前你可能这么写:
[我的一个view set数值:xx];
那么你现在如果这么写:
[[我的一个view animator] set数值:xx],它就会动。
想在View中打开Core Animation支持,你可以用以下方法实现:
[我的view setWantsLayer:YES];
或是
我的view. setWantsLayer= YES; 这是Objective C 2.0的写法
再或者在Interface Builder中打开这个选项:
创建支持Core Animation的View
接下来用一个简单的例子介绍一下如何做一个基于层的View用来支持Core Animation。
首先在Interface Builder里拽一个Custom View,拽进窗口,改名,随便叫什么,比如我改为TestView:
在菜单中选择Write Class…,保存到项目中。你就可以在这个View里面做点能动的东西了。
在层中画图
你可以直接在View里面使用drawLayer:方法画层。不过一般来说,我们都会在层中使用一些图片。要给CALayer设置图片,你只需使用xxlayer.contents指定contents的属性为一个图片就可以在层上显示图片。只是CALayer需要的图片类型是CGImageRef,而我们比较容易获取的图片类型是NSImage。你可以使用下面的函数将NSImage转换为CGImageRef:
- (CGImageRef)nsImageToCGImageRef:(NSImage*)image;
{
NSData * imageData = [image TIFFRepresentation];
CGImageRef imageRef;
if(imageData)
{
CGImageSourceRef imageSource =
CGImageSourceCreateWithData(
(CFDataRef)imageData, NULL);
imageRef = CGImageSourceCreateImageAtIndex(
imageSource, 0, NULL);
}
return imageRef;
}
把这个函数复制到你的View代码中,我们会需要用到它。
现在我们来做一个方法,叫做setupLayers:
-(void) setupLayers
{
}
然后在你的awakeFromNib中加入:
[self setupLayers];
我们会在setupLayers这个方法中建立层,别忘了在你的.h文件中也加入这个方法的定义。
接下来,在项目中添加一个图片,比如我叫它1.png,我会在层中显示这个图片:
加入之后,在setupLayers方法中加入下面几句话:
CGRect viewFrame=NSRectToCGRect([self frame]);
CALayer *rootLayer=self.layer;
rootLayer.frame=viewFrame;
这三句话的意思是,获得这个View本身的层,并将其大小设定为view的大小。这个层就是我们的基础层,我们之后添加的层会在这个rootLayer之上。
定义一个CALayer:
CALayer *layer1;
然后创建这个层:
layer1=[CALayer layer] ;
然后获取我们刚才加进项目的图片:
NSImage *image1=[NSImage imageNamed:@"1"] ;
把这个图片设置在layer1上显示:
layer1.contents=(id)[self nsImageToCGImageRef:image1];
设置层的大小和位置:
layer1.frame=CGRectMake(0,0,320,240);
layer1.position=CGPointMake(viewFrame.size.width/2, viewFrame.size.height/2); //定位到屏幕中间
添加到rootLayer上:
[rootLayer addSublayer:layer1];
这幅图片就显示出来了:
在你那里看起来和这幅图不一样的原因是我画了一下背景:
- (void)drawRect:(NSRect)rect
{
//画背景
NSGradient *gradient=[[NSGradient alloc] initWithStartingColor: [NSColor colorWithCalibratedWhite:0.35 alpha:1.0]
endingColor:[NSColor colorWithCalibratedWhite:0 alpha:1.0]];
[gradient drawInRect:rect angle:90.0];
}
View的drawRect:方法可以和Core Animation并存,因此你的程序会先画出这个渐变的背景,然后在上面画这个带图片的层。
开始动画
这个教学里我暂时不打算说太多复杂的内容,先来点能看到实际效果的东西。我们将这幅图横向旋转一下,这个效果有点像Dashboard中进行设置的感觉:
添加下面的代码:
-(void)flip
{
[CATransaction setValue:[NSNumber numberWithFloat:1.0] forKey:kCATransactionAnimationDuration];
CABasicAnimation *FlipAnimation=[CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
FlipAnimation.timingFunction= [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
FlipAnimation.toValue= [NSNumber numberWithFloat:M_PI];
FlipAnimation.duration=1;
FlipAnimation.fillMode=kCAFillModeForwards;
FlipAnimation.removedOnCompletion=NO;
[layer1 addAnimation:FlipAnimation forKey:@"flip"];
[CATransaction commit];
}
在layer1 addAnimation的时候,动画就加进去并自动运行了。这段代码的意思是延y轴将layer1旋转180度,持续时间1秒,旋转完成后保持状态。
“transform.rotation.y”你可以在Core Animation的文档中查到,用于旋转y轴。
FlipAnimation.toValue= [NSNumber numberWithFloat:M_PI];
中的M_PI就是pi,因为旋转角度使用弧度而不是角度,所以pi就是半个圆,也就是180度。
FlipAnimation.fillMode=kCAFillModeForwards;
FlipAnimation.removedOnCompletion=NO;
而上面这两句话的意思就是旋转之后保持状态。否则旋转的动画完成之后,动画将自动删除,而你的层也会回到初始状态。
在awakeFromNib中加入下面代码执行:
[self flip];
执行之后你就会看到这幅图片按照动画的效果横向旋转了180度。
这个教学还没完,主要是我的网今天有点问题,周末了有点懒。下次可能会继续介绍点更好玩的Core Animation动画。关于如何继续这个教学,我现在没有太多好想法,如果你有什么点子,可以在这里留言,我们一起尝试着用Core Animation实现一下。另外给图片加了点水印,还请亲爱的读者谅解。
下次将介绍一下多个动作的动画效果,先预告一下:)