iTunes的CoverFlow照片倒影效果很酷,因为它使一幅简单的照片在界面上看起来很真实。

那么如何用Core Animation的CALayer做出这种效果,以便增加动画的处理,这就是下文要研究的课题。

在这个例子里,我们做了三个CALayer,分别叫做imgLayer,用于显示图片;reflectionLayer,用于显示倒影和shadowLayer,做为倒影的遮罩。这个例子假设您会使用Photoshop进行简单的图片处理。

 

 

 

假定我们已经创建了一个根层(root layer)叫做mainLayer。我们下面的所有层都做为mainLayer的子层出现。

一个照片的倒影效果由两个部分组成,一部分是照片,当然另一部分是倒影。照片的显示很简单,我们只需要用任何方法把照片读取成CGImageRef(可以参阅本站另一篇关于图片数据类型转换的文章),就可以做为contents提供给CALayer。代码看起来是这样的:

NSImage *img=[[NSImage imageNamed:@"cover2"] retain];

imgLayer.contents=(id)[self nsImageToCGImageRef:img];

其中nsImageToCGImageRef:方法是我们用来将NSImage*转化为CGImageRef的方法。这样,imgLayer这个Core Animation层就会包含一个叫做cover2的图片。将这个层添加到mainLayer中,这幅图片就会显示在屏幕上。以下是代码:

 

[mainLayer addSublayer:imgLayer];

 

这样,图片就显示出来了。那么如何处理倒影呢?我们知道,CALayer是可以进行三维坐标转换的,那么我们要做的,就是复制一个imgLayer的内容(也就是我们要显示的图片),将它的y坐标进行倒转,就会显示出来。

 

reflectionLayer.contents=imgLayer.contents;

reflectionLayer.opacity = 0.5;

reflectionLayer.frame=CGRectOffset(imgLayer.frame, 0.5, -(imgLayer.bounds.size.height) + 0.5);

reflectionLayer.transform = CATransform3DMakeScale(1.0, -1.0, 1.0); 

 

注意最后一行:我们使用了CATransform3DMakeScale这个方法,将reflectionLayer层的y坐标进行了转换。但是问题来了,这样一来,图片显示的有点太多了。一个图片加一个倒置的图片显然还不是我们想要的效果。我们应该缩短这副倒影图片,使它看起来融入了画面中一样,这样才会比较像。

 

我们注意到,CALayer有一个属性叫做.mask,可以将一个层做为当前层的遮罩。这正是我们需要的。要增加这个遮罩,我们有两种方法去实现:1 Leopard中提供了一个叫做NSGradient的类,可以用来方便地制作渐变;2 我们自己画一个需要的渐变模板。 这两种方法都很简单。这里我们选择第二种方法:做一个遮罩图。用photoshop来实现:

 

 

创建一个空文档,将背景设置为完全透明。在photoshop中选择渐变,按照上图的样子画一个渐变。注意前景色可以是任何颜色,背景色必须是透明。CALayer的mask属性只会使用遮罩层的alpha通道,这个渐变是什么颜色是没关系的。

 

接下来的工作就很简单了。我们创建一个shadowLayer层,把刚刚画出来的遮罩图读进来,做为模板蒙在reflectionLayer上。bing! 工作完成。

 

 

shadowLayer.frame=reflectionLayer.bounds;

reflectionLayer.mask=shadowLayer;

 

需要注意的是,需要把shadowLayer的frame属性设置为reflectionLayer的bounds,这样才会在适当的地方设置模板。

 

全部的代码在下面,有了这段简单的代码,你就可以对这个带倒影的层设置任何你想要的动画效果了。

 

 

 

imgLayer=[[CALayer layer] retain];

imgLayer.bounds=CGRectMake(0, 0, 140, 120);

imgLayer.position=CGPointMake(mainLayer.bounds.size.width/2, mainLayer.bounds.size.width/2);

NSImage *img=[[NSImage imageNamed:@"cover2"] retain];

imgLayer.contents=(id)[self nsImageToCGImageRef:img];

[mainLayer addSublayer:imgLayer];

reflectionLayer=[[CALayer layer]retain];

reflectionLayer.contents=imgLayer.contents;

reflectionLayer.opacity = 0.5;

reflectionLayer.frame=CGRectOffset(imgLayer.frame, 0.5,

-(imgLayer.bounds.size.height) + 0.5);

         reflectionLayer.transform = CATransform3DMakeScale(1.0, -1.0, 1.0); 

reflectionLayer.sublayerTransform = reflectionLayer.transform;

[mainLayer addSublayer:reflectionLayer];

shadowLayer = [[CALayer layer] retain];

NSImage *shadowMask=[[NSImage imageNamed:@"shadowmask"] retain];

shadowLayer.contents=(id)[self nsImageToCGImageRef:shadowMask];

shadowLayer.frame=reflectionLayer.bounds;

reflectionLayer.mask=shadowLayer;

 

*如需转载本文请注明转自cocoachina.com苹果开发中文站,谢谢。