2013-12-10 26 views
11

我正在绘制饼图的每个切片使用CAShapeLayer的饼图。即使当一个扇形片的结束角度等于相邻片的起始角时,如果片之间的边界处于某个角度,抗锯齿就会导致出现在每个小片片之间的底层背景色。相邻CAShapeLayer Antialiasing问题

http://i.stack.imgur.com/Qdu8d.png

我想同时仍然使用抗锯齿所以造成馅饼车看起来还是平滑,消除片之间的微小间隙。从概念上讲,似乎是否有办法将抗锯齿应用到整个CALayer,并且在所有的馅饼切片被绘制完之后它是馅饼切片子图层,那么这将实现诀窍...馅饼切片将被相互抗锯齿而不是进入背景。

我已经玩过尽可能多的CALayer属性,因为我可以想象并且很难找到关于此的更多信息。有任何想法吗?

更新:请参阅下面的答案。

回答

5

UPDATE:罗布的答案是相当不错的,但在其他抗锯齿问题可能的结果。我通过沿着每个扇形片的端角画出1pt宽的径向线,结束了'填充'间隙,每条线与相邻片的颜色相同。这些线是在比馅饼切片更低的z索引处绘制的,因此它们在下面。下面是他们的样子,而不在上面绘制圆形切片:

The filler lines with no slices drawn.

而这里的最终产品:

Final result with lines underneath and slices on top.

8

你可能不会让你的派片边缘完全没有裂缝。最简单的解决方案是不要尝试。

而不是让你的馅饼切片在边缘相遇,使它们重叠。绘制第一个切片作为一个完整的光盘:

first slice

再画第二层作为一个完整的盘,除了第一层的正确面积:

second slice

然后绘制第三片作为全盘,除了前两片的正确区域:

third slice

等等:

fourth slicefifth slice

这里是我的代码:

#import "PieView.h" 

@implementation PieView { 
    NSMutableArray *slices; 
} 

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     // Initialization code 
    } 
    return self; 
} 

- (void)layoutSubviews { 
    [super layoutSubviews]; 
    [self layoutSliceLayers]; 
} 

- (void)layoutSliceLayers { 
    if (slices == nil) { 
     [self createSlices]; 
    } 
    [slices enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 
     [self layoutSliceLayer:obj index:idx]; 
    }]; 
} 

static const int kSliceCount = 5; 

- (void)createSlices { 
    slices = [NSMutableArray arrayWithCapacity:kSliceCount]; 
    for (int i = 0; i < kSliceCount; ++i) { 
     [slices addObject:[self newSliceLayerForIndex:i]]; 
    } 
} 

- (CAShapeLayer *)newSliceLayerForIndex:(int)i { 
    CAShapeLayer *layer = [CAShapeLayer layer]; 
    layer.fillColor = [UIColor colorWithWhite:(CGFloat)i/kSliceCount alpha:1].CGColor; 
    [self.layer addSublayer:layer]; 
    return layer; 
} 

- (void)layoutSliceLayer:(CAShapeLayer *)layer index:(int)index { 
    layer.position = [self center]; 
    layer.path = [self pathForSliceIndex:index].CGPath; 
} 

- (CGPoint)center { 
    CGRect bounds = self.bounds; 
    return CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds)); 
} 

- (UIBezierPath *)pathForSliceIndex:(int)i { 
    CGFloat radius = [self radius]; 
    CGFloat fudgeRadians = 5/radius; 
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointZero 
     radius:radius startAngle:2 * M_PI * i/kSliceCount 
     endAngle:2 * M_PI clockwise:YES]; 
    [path addLineToPoint:CGPointZero]; 
    [path closePath]; 
    return path; 
} 

- (CGFloat)radius { 
    CGSize size = self.bounds.size; 
    return 0.9 * MIN(size.width, size.height)/2; 
} 

@end 
+0

非常感谢您的答复,罗布。我确实在某个时候尝试了这个解决方案,并且看到来自较暗的底层的抗锯齿伪像正在反锯齿到背景中。它出现在饼图周围的一个微妙的黑色边缘,在较浅的彩色切片的外边缘处尤为明显。我所描述的径向填充解决方案似乎运作良好。 – Aaron

+0

@Aaron当你使用反锯齿时,你最终会在纯色的有效锯齿形状周围形成一圈颜色+ alpha像素。对于具有相同轮廓的多个形状执行此操作时,有效混叠的内部区域看起来不错,但防混叠区域将具有颜色(n)+ alpha重叠颜色(n-1)+ alpha重叠... color(0) +阿尔法。这解释了你所看到的效果。 –