2013-12-10 29 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) +阿爾法。這解釋了你所看到的效果。 –