在Core Animation的层中使用遮罩使图片的某些部分变为透明是非常简单的事情,你只需要建立一个遮罩层,设置为另一个层的mask即可。相关信息在本站的 Core
Animation:用最少代码画出照片倒影效果
 中有所提及。只是之前例子中的遮罩是使用Photoshop进行创建的。

本文通过一个简单例子,直接创建一个CGImageRef图片做为遮罩,继续讲解如何在Core Animation中使用遮罩。

本文的例子实现了以下几个方面:

- 创建一个NSImage,用NSBezierPath填充。

- 将NSImage转换为CGImageRef (本站有相关文章讲解如何转换图片数据类型)。

- 建立三个CALayer,分别用于:显示遮罩图片、被遮罩的图片以及合并后的效果图。

作者:Matthieu Cormier 原文地址

相关代码如下:

- (void)awakeFromNib {    

[self maskTest]; 

}

 

- (CGImageRef)createMaskImage {

[[NSColor colorWithCalibratedWhite:1.0 alpha:1.0set];

float minX = 0;

float minY = 0;

float maxX = 100;

float maxY = 100;  

NSBezierPath* path = [NSBezierPath bezierPath];

NSPoint topLeft     = NSMakePoint (minX, maxY);

NSPoint topRight    = NSMakePoint (maxX, maxY);

NSPoint bottomRight = NSMakePoint (maxX, minY);

NSPoint bottomLeft  = NSMakePoint (minX, minY);

NSPoint centerPoint = NSMakePoint((maxX - minX) * 0.5,
(maxY - minY) * 0.5);

[path moveToPoint:topLeft];

[path lineToPoint:topRight];  

[path curveToPoint:centerPoint controlPoint1:NSMakePoint((maxX
- minX) * 0.5, maxY) 

 controlPoint2:centerPoint];  

[path curveToPoint:bottomRight controlPoint1:NSMakePoint((maxX
- minX) * 0.5, minY) 

 controlPoint2:bottomRight];

[path lineToPoint:bottomLeft];

NSImage* maskImage = [[NSImage allocinitWithSize:NSMakeSize(100100)];

[maskImage lockFocus];

{

[[NSColor colorWithCalibratedWhite:1.0 alpha:1.0set];

[path fill];

[path stroke];

}

[maskImage unlockFocus];

    

CGImageSourceRef source;

source = CGImageSourceCreateWithData((CFDataRef)[maskImage TIFFRepresentation], NULL);

CGImageRef maskRef =  CGImageSourceCreateImageAtIndex(source, 0NULL);

[maskImage release];

return maskRef;

}

 

 

 

- (void)maskTest {

CGRect viewFrame = NSRectToCGRectself.frame
);

viewFrame.origin.y = 0;

// create a layer and match its frame to the view’s frame

self.wantsLayer = YES;

CALayer* mainLayer = self.layer;

mainLayer.name = @"mainLayer";

mainLayer.frame = viewFrame;

mainLayer.delegate = self;

// causes the layer content to be drawn in -drawRect:

[mainLayer setNeedsDisplay];

CGFloat midX = CGRectGetMidX( mainLayer.frame );

CGFloat midY = CGRectGetMidY( mainLayer.frame );

// create a "container" layer for all content layers.

// same frame as the view’s master layer, automatically

// resizes as necessary.    

CALayer* contentContainer = [CALayer layer];
   

contentContainer.bounds           = mainLayer.bounds;

contentContainer.delegate         = self;

contentContainer.anchorPoint      = CGPointMake(0.5,0.5);

contentContainer.position         = CGPointMake( midX, midY );

contentContainer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;

contentContainer.borderWidth = 2.0;

contentContainer.borderColor = SFWhiteColor;

[self.layer addSublayer:contentContainer];

CALayer* boxLayer = [CALayer layer];
   

boxLayer.frame           = CGRectMake(00100100);

boxLayer.backgroundColor =  CGColorCreateGenericRGB(0.0f,0.0f,0.0f,1.0f);

boxLayer.position = CGPointMake(11010);

boxLayer.anchorPoint = CGPointMake(0,0);

CALayer* maskLayer = [CALayer layer];
   

maskLayer.frame           = CGRectMake(00100100);

maskLayer.position = CGPointMake(00);

maskLayer.anchorPoint = CGPointMake(0,0);
 

CGImageRef maskImage = [self createMaskImage];

[maskLayer setContents :( id)maskImage];

[boxLayer setMask:maskLayer];

[contentContainer addSublayer:boxLayer];

[contentContainer layoutSublayers];

[contentContainer layoutIfNeeded]; 

}

 

例子项目文件在此下载