使用另一个CALayer屏蔽CALayer

我正试着用CALayers制作甜甜圈。 一个CALayer将是一个大圆圈,另一个将是一个位于其中心的较小圆圈,将其遮盖。

大圆圈显示正常,但每当我调用circle.mask = circleMask; 然后视图显示为空。

这是我的代码:

AriDonut.h

 #import  @interface AriDonut : UIView -(id)initWithRadius:(float)radius; @end 

AriDonut.m

 #import "AriDonut.h" #import  @implementation AriDonut -(id)initWithRadius:(float)radius{ self = [super initWithFrame:CGRectMake(0, 0, radius, radius)]; if(self){ //LARGE CIRCLE CALayer *circle = [CALayer layer]; circle.bounds = CGRectMake(0, 0, radius, radius); circle.backgroundColor = [UIColor redColor].CGColor; circle.cornerRadius = radius/2; circle.position = CGPointMake(radius/2, radius/2); //SMALL CIRLCE CALayer *circleMask = [CALayer layer]; circleMask.bounds = CGRectMake(0, 0, 10, 10); circleMask.cornerRadius = radius/2; circleMask.position = circle.position; //circle.mask = circleMask; [self.layer addSublayer:circle]; } return self; } 

我试过像这样设置大圆圈的超级层nil:

 CALayer *theSuper = circle.superlayer; theSuper = nil; 

但它并没有什么不同。

我也尝试将Circle的masksToBounds属性设置为YES和NO,但它没有任何区别。

有什么想法吗?

实际上,由于@David表示当前(iOS 5.1)CALayer蒙版无法反转,如果您想使用它们将透明孔制作成简单的圆形CALayer,则会出现问题。

你可以做一个圆环CALayer的backgroundColor透明,但给它一个borderColor和一个宽borderWidth 。 这是dunkin’代码:

  CALayer *theDonut = [CALayer layer]; theDonut.bounds = CGRectMake(0,0, radius, radius); theDonut.cornerRadius = radius/2; theDonut.backgroundColor = [UIColor clearColor].CGColor; theDonut.borderWidth = radius/5; theDonut.borderColor = [UIColor orangeColor].CGColor; [self.layer addSublayer:theDonut]; 

它是用作遮罩的遮罩层内容的alpha值。 (如果您将蒙版添加为子图层而不是将其用作蒙版。当用作蒙版时,子图层覆盖的所有内容都将可见。当用作蒙版时,子图层未覆盖的所有内容都将被隐藏。)

由于您的小圆圈是完全透明的,所以一切都被遮盖(隐藏)。 如果你将它的backgroundColor设置为任何完全不透明的颜色(只有alpha值用于蒙版),那么它将让这些像素通过。

请注意,这与您想要的相反。 这将使您只看到“甜甜圈的洞”可见。 没有内置的方法来做反向掩码而是你必须以其他方式绘制掩码的内容,比如使用CAShapeLayer或使用drawInContext: .

使用UIBezierPath和CAShapeLayer作为屏蔽层非常容易。 编写的代码示例就像它在UIView子类中一样。

Objective-C的:

 CGRect outerRect = self.bounds; CGFloat inset = 0.2 * outerRect.size.width; // adjust as necessary for more or less meaty donuts CGFloat innerDiameter = outerRect.size.width - 2.0 * inset; CGRect innerRect = CGRectMake(inset, inset, innerDiameter, innerDiameter); UIBezierPath *outerCircle = [UIBezierPath bezierPathWithRoundedRect:outerRect cornerRadius:outerRect.size.width * 0.5]; UIBezierPath *innerCircle = [UIBezierPath bezierPathWithRoundedRect:innerRect cornerRadius:innerRect.size.width * 0.5]; [outerCircle appendPath:innerCircle]; CAShapeLayer *maskLayer = [CAShapeLayer new]; maskLayer.fillRule = kCAFillRuleEvenOdd; // Going from the outside of the layer, each time a path is crossed, add one. Each time the count is odd, we are "inside" the path. maskLayer.path = outerCircle.CGPath; self.layer.mask = maskLayer; 

迅速:

 let outerRect = self.bounds let inset: CGFloat = 0.2 * outerRect.width // adjust as necessary for more or less meaty donuts let innerDiameter = outerRect.width - 2.0 * inset let innerRect = CGRect(x: inset, y: inset, width: innerDiameter, height: innerDiameter) let outerCircle = UIBezierPath(roundedRect: outerRect, cornerRadius: outerRect.width * 0.5) let innerCircle = UIBezierPath(roundedRect: innerRect, cornerRadius: innerRect.width * 0.5) outerCircle.appendPath(innerCircle) let mask = CAShapeLayer() mask.fillRule = kCAFillRuleEvenOdd mask.path = outerCircle.CGPath self.layer.mask = mask 

我成功地用CAShapeLayer屏蔽了CALayer 。 要指定屏蔽CAShapeLayer的形状,我使用了UIBezierPath

我在这个问题的答案中发布了代码: 如何获取UIBezierPath的反向路径 。 对于甜甜圈形状取消注释评论线。